Как инвертировать BooleanToVisibilityConverter?
я использую BooleanToVisibilityConverter в WPF для привязки Visibility свойство элемента управления к Boolean. Это работает нормально, но я бы хотел, чтобы один из элементов управления скрывался, если логическое значение true, и показать, если это false.
16 ответов:
реализовать свою собственную реализацию IValueConverter. Пример реализации находится в
http://msdn.microsoft.com/en-us/library/system.windows.data.ivalueconverter.aspx
в вашем методе преобразования, пусть он возвращает значения, которые вы хотели бы вместо значений по умолчанию.
вместо инвертирования, вы можете достичь той же цели, используя общий
IValueConverterреализация, которая может преобразовать логическое значение в настраиваемые!--13--> целевые значения 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); } }далее, подкласс его где
TиVisibility:public sealed class BooleanToVisibilityConverter : BooleanConverter<Visibility> { public BooleanToVisibilityConverter() : base(Visibility.Visible, Visibility.Collapsed) {} }наконец, это, как вы могли бы использовать
BooleanToVisibilityConverterвыше в XAML и настроить его, например, использоватьCollapsedдля настоящих иVisibleдля ложь:<Application.Resources> <app:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" True="Collapsed" False="Visible" /> </Application.Resources>эта инверсия полезна, когда вы хотите привязать к логическому свойству с именем
IsHiddenв противоположностьIsVisible.
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>
есть еще конвертеры WPF проект на Codeplex. В их документации они говорят, что вы можете использовать их MapConverter для преобразования из перечисления видимости в 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>
еще один способ привязки логического значения ViewModel (IsButtonVisible) к свойству видимости элемента управления xaml. Нет кодирования, нет преобразования, просто стиль.
<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>
или настоящий ленивый человек, просто используйте то, что уже есть, и переверните его:
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; } }
Я только что сделал сообщение об этом. Я использовал ту же идею, что и Майкл Холиос. Только я использовал свойства вместо использования параметра "объект".
привязка видимости к значению bool в WPF
использование свойств делает его более читаемым, на мой взгляд.<local:BoolToVisibleOrHidden x:Key="BoolToVisConverter" Collapse="True" Reverse="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
Если вам не нравится писать пользовательский конвертер, вы можете использовать триггеры данных для решения этой проблемы:
<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>
написать свой собственный конвертировать.
public class ReverseBooleanToVisibilityConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { // your converter code here } }
Я искал более общий ответ, но не смог его найти. Я написал конвертер, который может помочь другим.
Он основан на том, что нам нужно различать шесть разных случаев:
- True 2 Видимый, False 2 Скрытый
- True 2 Видно, False 2 Рухнул
- True 2 Скрытый, False 2 Видимый
- True 2 Рухнул, False 2 Виден
- True 2 Скрыто, False 2 Рухнул
- True 2 Рухнул, False 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.
С QuickConverter вы можете написать логику конвертера встроенную с вашим BindingExpression
вот инвертированный преобразователь BooleanToVisibility:
Visibility="{qc:Binding '!$P ? Visibility.Visible : Visibility.Collapsed', P={Binding Example}}"вы можете добавить QuickConverter через NuGet. Ознакомьтесь с документацией по установке. Ссылка:https://quickconverter.codeplex.com/
простая односторонняя версия, которая может быть использована следующим образом:
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(); } }
конвертировать все во все (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>
Я знаю, что это датировано, но вам не нужно ничего повторно внедрять.
что я сделал, так это отрицать значение свойства следующим образом:
<!-- 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); } }и это работает просто отлично!
Я что-то пропустила?
Comments