Я использую BooleanToVisibilityConverter
в WPF для привязки Visibility
свойства элемента управления к Boolean
. Это работает нормально, но я бы хотел, чтобы один из элементов управления скрыл, если логическое значение есть true
, и показал, если он false
.
.net
wpf
binding
visibility
Рубен Бартелинк
источник
источник
Ответы:
Реализуйте свою собственную реализацию IValueConverter. Пример реализации находится на
http://msdn.microsoft.com/en-us/library/system.windows.data.ivalueconverter.aspx
В вашем методе Convert попросите его вернуть желаемые значения вместо значений по умолчанию.
источник
Вместо инвертирования вы можете достичь той же цели, используя универсальную
IValueConverter
реализацию, которая может преобразовывать логическое значение в настраиваемые целевые значения для истинного и ложного. Ниже представлена одна из таких реализаций: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
для использования для true иVisible
для false:<Application.Resources> <app:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" True="Collapsed" False="Visible" /> </Application.Resources>
Эта инверсия полезна, когда вы хотите выполнить привязку к логическому свойству с именем
IsHidden
вместоIsVisible
.источник
Visibility
свойство в модели представления.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>
источник
else if (value is bool?)
части, ReSharper говорит мне «Expression всегда ложно». Кроме того,if (flag)
часть можно более кратко переписать какreturn flag ? Visibility.Visible : Visibility.Collapsed;
.var nullable = (bool?)value; flag = nullable.GetValueOrDefault();
можно сделать намного короче и проще:flag = (bool?)value ?? false;
Напишите свой собственный - лучшее решение на данный момент. Вот пример конвертера, который может работать как в нормальном, так и в инвертированном режиме. Если у вас есть проблемы с этим, просто спросите.
[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>
источник
BooleanToVisibilityConverter
, проверив параметр наParameter direction = Parameter.Normal; if (parameter != null) direction = (Parameter)Enum.Parse(typeof(Parameter), (string)parameter);
Также на Codeplex есть проект WPF Converters . В их документации говорится, что вы можете использовать их MapConverter для преобразования из перечисления Visibility в 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; } }
источник
Если вам не нравится писать собственный конвертер, вы можете использовать триггеры данных для решения этой проблемы:
<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>
источник
Я только что написал об этом. Я использовал ту же идею, что и Майкл Холиос. Только я использовал Свойства вместо использования «параметра объекта».
На
мой взгляд, привязка видимости к значению типа 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
источник
Я искал более общий ответ, но не нашел. Я написал конвертер, который может помочь другим.
Он основан на том, что нам нужно различать шесть разных случаев:
Вот моя реализация для первых 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/
источник
Напишите свой собственный конверт.
public class ReverseBooleanToVisibilityConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { // your converter code here } }
источник
Простая односторонняя версия, которую можно использовать так:
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>
источник
Вместо того, чтобы писать свой собственный код / изобретать заново, рассмотрите возможность использования 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 также весьма полезен для множества других сценариев.
источник
Я знаю, что это устарело, но вам не нужно ничего переделывать.
Что я сделал, так это отменил значение свойства следующим образом:
<!-- 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); } }
И работает отлично!
Я что-то упускаю?
источник