Comment inverser BooleanToVisibilityConverter?

J'utilise un BooleanToVisibilityConverter dans WPF pour lier la propriété Visibility d'un contrôle à un Boolean. Cela fonctionne bien, mais j'aimerais qu'un des contrôles cache si le booléen est true, et montre s'il est false.

120
demandé sur Ruben Bartelink 2009-02-11 01:41:50

16 réponses

Implémentez votre propre implémentation D'IValueConverter. Un exemple d'implémentation est à

Http://msdn.microsoft.com/en-us/library/system.windows.data.ivalueconverter.aspx

Dans votre méthode Convert, demandez-lui de renvoyer les valeurs que vous souhaitez au lieu des valeurs par défaut.

16
répondu Steve Mitcham 2015-02-27 12:32:47

Au lieu d'inverser, vous pouvez atteindre le même objectif en utilisant une implémentation IValueConverter générique qui peut convertir une valeur booléenne en valeurs cibles configurables pour true et false. Voici une telle mise en œuvre:

public class BooleanConverter<T> : IValueConverter
{
    public BooleanConverter(T trueValue, T falseValue)
    {
        True = trueValue;
        False = falseValue;
    }

    public T True { get; set; }
    public T False { get; set; }

    public virtual object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return value is bool && ((bool) value) ? True : False;
    }

    public virtual object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return value is T && EqualityComparer<T>.Default.Equals((T) value, True);
    }
}

Ensuite, la sous-classe où T est Visibility:

public sealed class BooleanToVisibilityConverter : BooleanConverter<Visibility>
{
    public BooleanToVisibilityConverter() : 
        base(Visibility.Visible, Visibility.Collapsed) {}
}

Enfin, voici comment vous pouvez utiliser BooleanToVisibilityConverter ci-dessus dans XAML et le configurer pour, par exemple, utiliser Collapsed pour true et Visible pour false:

<Application.Resources>
    <app:BooleanToVisibilityConverter 
        x:Key="BooleanToVisibilityConverter" 
        True="Collapsed" 
        False="Visible" />
</Application.Resources>

Cette inversion est utile quand vous voulez pour se lier à une propriété booléenne nommée IsHidden par opposition à IsVisible.

223
répondu Atif Aziz 2011-03-21 13:01:18
using System;
using System.Globalization;
using System.Windows;
using System.Windows.Data;

public sealed class BooleanToVisibilityConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        var flag = false;
        if (value is bool)
        {
            flag = (bool)value;
        }
        else if (value is bool?)
        {
            var nullable = (bool?)value;
            flag = nullable.GetValueOrDefault();
        }
        if (parameter != null)
        {
            if (bool.Parse((string)parameter))
            {
                flag = !flag;
            }
        }
        if (flag)
        {
            return Visibility.Visible;
        }
        else
        {
            return Visibility.Collapsed;
        }
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        var back = ((value is Visibility) && (((Visibility)value) == Visibility.Visible));
        if (parameter != null)
        {
            if ((bool)parameter)
            {
                back = !back;
            }
        }
        return back;
    }
}

Puis passez un true ou false comme ConverterParameter

       <Grid.Visibility>
                <Binding Path="IsYesNoButtonSetVisible" Converter="{StaticResource booleanToVisibilityConverter}" ConverterParameter="true"/>
        </Grid.Visibility>
47
répondu Simon 2012-08-27 05:31:26

Rédiger votre propre est la meilleure solution pour l'instant. Voici un exemple d'un convertisseur qui peut faire à la fois Normal et inversé. Si vous avez des problèmes avec cela, il suffit de demander.

[ValueConversion(typeof(bool), typeof(Visibility))]
public class InvertableBooleanToVisibilityConverter : IValueConverter
{
    enum Parameters
    {
        Normal, Inverted
    }

    public object Convert(object value, Type targetType,
                          object parameter, CultureInfo culture)
    {
        var boolValue = (bool)value;
        var direction = (Parameters)Enum.Parse(typeof(Parameters), (string)parameter);

        if(direction == Parameters.Inverted)
            return !boolValue? Visibility.Visible : Visibility.Collapsed;

        return boolValue? Visibility.Visible : Visibility.Collapsed;
    }

    public object ConvertBack(object value, Type targetType,
        object parameter, CultureInfo culture)
    {
        return null;
    }
}
<UserControl.Resources>
  <Converters:InvertableBooleanToVisibilityConverter x:Key="_Converter"/>
</UserControl.Resources>

<Button Visibility="{Binding IsRunning, Converter={StaticResource _Converter}, ConverterParameter=Inverted}">Start</Button>
40
répondu Michael Hohlios 2016-01-18 13:56:36

Il y a aussi le projet WPF Converters sur Codeplex. Dans leur documentation, ils disent que vous pouvez utiliser leur MapConverter pour convertir de L'énumération de visibilité en bool

<Label>
    <Label.Visible>
        <Binding Path="IsVisible">
            <Binding.Converter>
                <con:MapConverter>
                    <con:Mapping From="True" To="{x:Static Visibility.Visible}"/>
                    <con:Mapping From="False" To="{x:Static Visibility.Hidden}"/>
                </con:MapConverter>
            </Binding.Converter>
        </Binding>
    </Label.Visible>
</Label>
20
répondu Cameron MacFarland 2010-05-31 08:45:26

Une autre façon de lier la valeur booléenne ViewModel (IsButtonVisible) avec la propriété XAML Control Visibility. Pas de codage, pas de conversion, juste un style.

<Style TargetType={x:Type Button} x:Key="HideShow">
   <Style.Triggers>
      <DataTrigger Binding="{Binding IsButtonVisible}" Value="False">
          <Setter Property="Visibility" Value="Hidden"/>
      </DataTrigger>
   </Style.Triggers>
</Style>

<Button Style="{StaticResource HideShow}">Hello</Button>
13
répondu Marat Batalandabad 2016-01-11 16:20:48

Ou la vraie manière paresseuse de mans, faites juste usage de ce qui est déjà là et retournez-le:

public class InverseBooleanToVisibilityConverter : IValueConverter
{
    private BooleanToVisibilityConverter _converter = new BooleanToVisibilityConverter();

    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        var result = _converter.Convert(value, targetType, parameter, culture) as Visibility?;
        return result == Visibility.Collapsed ? Visibility.Visible : Visibility.Collapsed;
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        var result = _converter.ConvertBack(value, targetType, parameter, culture) as bool?;
        return result == true ? false : true;
    }
}
10
répondu Ross Oliver 2012-12-24 05:53:57

Je viens de faire un post à ce sujet. J'ai utilisé une idée similaire à celle de Michael Hohlios. Seulement, j'ai utilisé des propriétés au lieu d'utiliser le "paramètre d'objet".

Liaison de la visibilité à une valeur bool dans WPF

L'utilisation de propriétés le rend plus lisible, à mon avis.

<local:BoolToVisibleOrHidden x:Key="BoolToVisConverter" Collapse="True" Reverse="True" />
3
répondu Rhyous 2011-02-22 22:56:14

En voici un que j'ai écrit et utilisé beaucoup. Il utilise un paramètre de convertisseur booléen qui indique s'il faut ou non inverser la valeur, puis utilise XOR pour effectuer la négation:

[ValueConversion(typeof(bool), typeof(System.Windows.Visibility))]
public class BooleanVisibilityConverter : IValueConverter
{
    System.Windows.Visibility _visibilityWhenFalse = System.Windows.Visibility.Collapsed;

    /// <summary>
    /// Gets or sets the <see cref="System.Windows.Visibility"/> value to use when the value is false. Defaults to collapsed.
    /// </summary>
    public System.Windows.Visibility VisibilityWhenFalse
    {
        get { return _visibilityWhenFalse; }
        set { _visibilityWhenFalse = value; }
    }

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        bool negateValue;
        Boolean.TryParse(parameter as string, out negateValue);

        bool val = negateValue ^ System.Convert.ToBoolean(value); //Negate the value when negateValue is true using XOR
        return val ? System.Windows.Visibility.Visible : _visibilityWhenFalse;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        bool negateValue;
        Boolean.TryParse(parameter as string, out negateValue);

        if ((System.Windows.Visibility)value == System.Windows.Visibility.Visible)
            return true ^ negateValue;
        else
            return false ^ negateValue;
    }
}

Voici une table de vérité XOR pour référence:

        XOR
        x  y  XOR
        ---------
        0  0  0
        0  1  1
        1  0  1
        1  1  0
3
répondu xr280xr 2015-02-27 16:29:38

Si vous n'aimez pas écrire un convertisseur personnalisé, vous pouvez utiliser des déclencheurs de données pour résoudre ce problème:

<Style.Triggers>
        <DataTrigger Binding="{Binding YourBinaryOption}" Value="True">
                 <Setter Property="Visibility" Value="Visible" />
        </DataTrigger>
        <DataTrigger Binding="{Binding YourBinaryOption}" Value="False">
                 <Setter Property="Visibility" Value="Collapsed" />
        </DataTrigger>
</Style.Triggers>
3
répondu Haim Bendanan 2016-11-02 20:38:16

Écrivez votre propre converti.

public class ReverseBooleanToVisibilityConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
   {
       // your converter code here
   }
}
1
répondu Muad'Dib 2009-02-10 22:45:44

Je cherchais une réponse plus générale, mais je ne pouvais pas la trouver. J'ai écrit un convertisseur qui pourrait aider les autres.

Il est basé sur le fait que nous devons distinguer six cas différents:

  • Vrai 2 Visible, Faux 2 Caché
  • Vrai 2 Visible, Faux 2 S'Est Effondré
  • Vrai 2 Caché, Faux 2 Visible
  • Vrai 2 S'Est Effondré, Faux 2 Visible
  • Vrai 2 Cachés, Faux 2 S'Est Effondré
  • Vrai 2 S'Est Effondré, Faux 2 Caché

Voici mon implémentation pour les 4 premiers cas:

[ValueConversion(typeof(bool), typeof(Visibility))]
public class BooleanToVisibilityConverter : IValueConverter
{
    enum Types
    {
        /// <summary>
        /// True to Visible, False to Collapsed
        /// </summary>
        t2v_f2c,
        /// <summary>
        /// True to Visible, False to Hidden
        /// </summary>
        t2v_f2h,
        /// <summary>
        /// True to Collapsed, False to Visible
        /// </summary>
        t2c_f2v,
        /// <summary>
        /// True to Hidden, False to Visible
        /// </summary>
        t2h_f2v,
    }
    public object Convert(object value, Type targetType,
                          object parameter, CultureInfo culture)
    {
        var b = (bool)value;
        string p = (string)parameter;
        var type = (Types)Enum.Parse(typeof(Types), (string)parameter);
        switch (type)
        {
            case Types.t2v_f2c:
                return b ? Visibility.Visible : Visibility.Collapsed; 
            case Types.t2v_f2h:
                return b ? Visibility.Visible : Visibility.Hidden; 
            case Types.t2c_f2v:
                return b ? Visibility.Collapsed : Visibility.Visible; 
            case Types.t2h_f2v:
                return b ? Visibility.Hidden : Visibility.Visible; 
        }
        throw new NotImplementedException();
    }

    public object ConvertBack(object value, Type targetType,
        object parameter, CultureInfo culture)
    {
        var v = (Visibility)value;
        string p = (string)parameter;
        var type = (Types)Enum.Parse(typeof(Types), (string)parameter);
        switch (type)
        {
            case Types.t2v_f2c:
                if (v == Visibility.Visible)
                    return true;
                else if (v == Visibility.Collapsed)
                    return false;
                break;
            case Types.t2v_f2h:
                if (v == Visibility.Visible)
                    return true;
                else if (v == Visibility.Hidden)
                    return false;
                break;
            case Types.t2c_f2v:
                if (v == Visibility.Visible)
                    return false;
                else if (v == Visibility.Collapsed)
                    return true;
                break;
            case Types.t2h_f2v:
                if (v == Visibility.Visible)
                    return false;
                else if (v == Visibility.Hidden)
                    return true;
                break;
        }
        throw new InvalidOperationException();
    }
}

Exemple:

Visibility="{Binding HasItems, Converter={StaticResource BooleanToVisibilityConverter}, ConverterParameter='t2v_f2c'}"

Je pense que les paramètres sont faciles à retenir.

J'espère que ça aide quelqu'un.

1
répondu Ron 2017-03-10 23:12:28

Vous pouvez utiliser QuickConverter.

Avec QuickConverter, vous pouvez écrire la logique du convertisseur en ligne avec votre BindingExpression

Voici un convertisseur booleantovisibility inversé:

Visibility="{qc:Binding '!$P ? Visibility.Visible : Visibility.Collapsed', P={Binding Example}}"

Vous pouvez ajouter QuickConverter via NuGet. Jetez un oeil à la documentation pour l'installation. Lien: https://quickconverter.codeplex.com/

1
répondu Felix Keil 2017-03-16 11:24:43

Une version simple à sens unique qui peut être utilisée comme ceci:

Visibility="{Binding IsHidden, Converter={x:Static Ui:Converters.BooleanToVisibility}, ConverterParameter=true}

Peut être implémenté comme ceci:

public class BooleanToVisibilityConverter : IValueConverter
{
  public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
  {
    var invert = false;

    if (parameter != null)
    {
      invert = Boolean.Parse(parameter.ToString());
    }

    var booleanValue = (bool) value;

    return ((booleanValue && !invert) || (!booleanValue && invert)) 
      ? Visibility.Visible : Visibility.Collapsed;
  }

  public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
  {
    throw new NotImplementedException();
  }
}
0
répondu Gregor Slavec 2012-09-04 19:32:16

Convertir tout en tout (bool, string, enum, etc):

public class EverythingConverterValue
{
    public object ConditionValue { get; set; }
    public object ResultValue { get; set; }
}

public class EverythingConverterList : List<EverythingConverterValue>
{

}

public class EverythingConverter : IValueConverter
{
    public EverythingConverterList Conditions { get; set; } = new EverythingConverterList();

    public object NullResultValue { get; set; }
    public object NullBackValue { get; set; }

    public object Convert(object value, Type targetType,
        object parameter, CultureInfo culture)
    {
        return Conditions.Where(x => x.ConditionValue.Equals(value)).Select(x => x.ResultValue).FirstOrDefault() ?? NullResultValue;
    }
    public object ConvertBack(object value, Type targetType,
        object parameter, CultureInfo culture)
    {
        return Conditions.Where(x => x.ResultValue.Equals(value)).Select(x => x.ConditionValue).FirstOrDefault() ?? NullBackValue;
    }
}

Exemples XAML:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                xmlns:conv="clr-namespace:MvvmGo.Converters;assembly=MvvmGo.WindowsWPF"
                xmlns:sys="clr-namespace:System;assembly=mscorlib">

<conv:EverythingConverter x:Key="BooleanToVisibilityConverter">
    <conv:EverythingConverter.Conditions>
        <conv:EverythingConverterValue ResultValue="{x:Static Visibility.Visible}">
            <conv:EverythingConverterValue.ConditionValue>
                <sys:Boolean>True</sys:Boolean>
            </conv:EverythingConverterValue.ConditionValue>
        </conv:EverythingConverterValue>
        <conv:EverythingConverterValue ResultValue="{x:Static Visibility.Collapsed}">
            <conv:EverythingConverterValue.ConditionValue>
                <sys:Boolean>False</sys:Boolean>
            </conv:EverythingConverterValue.ConditionValue>
        </conv:EverythingConverterValue>
    </conv:EverythingConverter.Conditions>

</conv:EverythingConverter>

<conv:EverythingConverter x:Key="InvertBooleanToVisibilityConverter">
    <conv:EverythingConverter.Conditions>
        <conv:EverythingConverterValue ResultValue="{x:Static Visibility.Visible}">
            <conv:EverythingConverterValue.ConditionValue>
                <sys:Boolean>False</sys:Boolean>
            </conv:EverythingConverterValue.ConditionValue>
        </conv:EverythingConverterValue>
        <conv:EverythingConverterValue ResultValue="{x:Static Visibility.Collapsed}">
            <conv:EverythingConverterValue.ConditionValue>
                <sys:Boolean>True</sys:Boolean>
            </conv:EverythingConverterValue.ConditionValue>
        </conv:EverythingConverterValue>
    </conv:EverythingConverter.Conditions>
</conv:EverythingConverter>

<conv:EverythingConverter x:Key="MarriedConverter" NullResultValue="Single">
    <conv:EverythingConverter.Conditions>
        <conv:EverythingConverterValue ResultValue="Married">
            <conv:EverythingConverterValue.ConditionValue>
                <sys:Boolean>True</sys:Boolean>
            </conv:EverythingConverterValue.ConditionValue>
        </conv:EverythingConverterValue>
        <conv:EverythingConverterValue ResultValue="Single">
            <conv:EverythingConverterValue.ConditionValue>
                <sys:Boolean>False</sys:Boolean>
            </conv:EverythingConverterValue.ConditionValue>
        </conv:EverythingConverterValue>
    </conv:EverythingConverter.Conditions>
    <conv:EverythingConverter.NullBackValue>
        <sys:Boolean>False</sys:Boolean>
    </conv:EverythingConverter.NullBackValue>
</conv:EverythingConverter>

0
répondu Ali Yousefie 2018-04-18 10:53:41

Je sais que c'est daté, mais, vous n'avez pas besoin de ré-implémenter quoi que ce soit.

Ce que j'ai fait était de nier la valeur sur la propriété comme ceci:

<!-- XAML code -->
<StackPanel Name="x"  Visibility="{Binding    Path=Specials, ElementName=MyWindow, Converter={StaticResource BooleanToVisibilityConverter}}"></StackPanel>    
<StackPanel Name="y"  Visibility="{Binding Path=NotSpecials, ElementName=MyWindow, Converter={StaticResource BooleanToVisibilityConverter}}"></StackPanel>        

....

//Code behind
public bool Specials
{
    get { return (bool) GetValue(SpecialsProperty); }
    set
    {
        NotSpecials= !value; 
        SetValue(SpecialsProperty, value);
    }
}

public bool NotSpecials
{
    get { return (bool) GetValue(NotSpecialsProperty); }
    set { SetValue(NotSpecialsProperty, value); }
}

Et ça marche très bien!

Est-ce que je manque quelque chose?

-3
répondu OscarRyz 2012-08-03 17:40:06