如何将 Boolean 转换为 VisibilityConverter?

我在 WPF 中使用 BooleanToVisibilityConverter将控件的 Visibility属性绑定到 Boolean。这个工作很好,但我希望其中一个控件隐藏布尔值是否为 true,并显示它是否为 false

115414 次浏览

实现您自己的 IValueConverter 实现

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

在 Convert 方法中,让它返回您想要的值,而不是默认值。

写你自己的改变。

public class ReverseBooleanToVisibilityConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
// your converter code here
}
}

还有一个关于科迪拉克斯的 WPF 转换器项目。在他们的文档中,他们说您可以使用他们的 图形转换器将可见性枚举转换为 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>
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;
}
}

然后将 true 或 false 作为 ConverterParameter 传递

       <Grid.Visibility>
<Binding Path="IsYesNoButtonSetVisible" Converter="{StaticResource booleanToVisibilityConverter}" ConverterParameter="true"/>
</Grid.Visibility>

写自己的是目前最好的解决方案。下面是一个转换器的例子,它可以同时进行正常和反向操作。如果你有任何问题,只要问。

[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>

我刚写了一篇关于这个的文章。我和 Michael Hohlios 用了类似的想法。只是,我使用了 Properties 而不是“ object 参数”。

将可见性绑定到 WPF 中的 bool 值

在我看来,使用属性使它更具可读性。

<local:BoolToVisibleOrHidden x:Key="BoolToVisConverter" Collapse="True" Reverse="True" />

您可以通过使用一个通用的 IValueConverter实现来实现相同的目标,而不必进行反转,该实现可以将布尔值转换为用于 true 和 false 的 可配置的目标值。下面是一个这样的实施方案:

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);
}
}

接下来,将其子类化,其中 TVisibility:

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

最后,这就是如何在 XAML 中使用 BooleanToVisibilityConverter并将其配置为,例如,使用 Collapsed表示 true,使用 Visible表示 false:

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

当您希望绑定到一个名为 IsHidden的布尔属性(而不是 IsVisible)时,这种反转非常有用。

我知道这已经过时了,但是,您不需要重新实现任何东西。

我所做的就是像这样抵消房产的价值:

<!-- 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); }
}

而且效果很好!

我错过了什么吗?

一个简单的单向版本,可以这样使用:

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

可以这样实施:

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();
}
}

或者像真正的懒人那样,只要利用现有的东西,然后把它翻过来:

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;
}
}

这个是我写的,用了很多次。它使用一个布尔转换器参数,该参数指示是否反转该值,然后使用 XOR 执行反转:

[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;
}
}

这里有一个 XOR 真值表供参考:

        XOR
x  y  XOR
---------
0  0  0
0  1  1
1  0  1
1  1  0

使用 xaml 控件可见性属性绑定 ViewModelBoolean 值(IsButtonVisible)的另一种方法。 没有编码,没有转换,只是造型。

<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>

如果您不喜欢编写自定义转换器,可以使用数据触发器来解决这个问题:

<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>

我在寻找一个更笼统的答案,但是找不到。我写了一个可以帮助别人的转换器。

它基于这样一个事实,即我们需要区分六种不同的情况:

  • 真2可见,假2隐藏
  • 真2可见,假2崩溃
  • 真2隐,假2可见
  • 真2崩溃,假2可见
  • 真2隐藏,假2崩溃
  • 真2崩溃,假2隐藏

以下是我对前4种情况的实现:

[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();
}
}

例如:

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

我觉得参数很好记。

希望能帮到别人。

你可以使用 快速转换器

使用 QuickConverter,您可以使用 BindingExpression 内联编写转换器逻辑

下面是一个倒置的 BooleanToVisiability 转换器:

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

您可以通过 NuGet 添加 QuickConverter。 查看安装的文档。 链接: 《 https://quickconverter.codeplex.com/》

将所有内容转换为所有内容(bool、 string、 enum 等) :

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;
}
}

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>

与其自己编写代码/重新发明,不如考虑使用 CalcBinding:

    // Automatic two way convertion of bool expression to Visibility and
// back if target property has such type: description
    

<Button Visibility="{c:Binding !IsChecked}" />
<Button Visibility="{c:Binding IsChecked, FalseToVisibility=Hidden}" />

CalcBinding 在许多其他场景中也非常有用。