Tôi đang sử dụng một BooleanToVisibilityConverter
WPF để ràng buộc thuộc Visibility
tính của điều khiển với a Boolean
. Điều này hoạt động tốt, nhưng tôi muốn một trong các điều khiển để ẩn nếu boolean là true
, và hiển thị nếu nó false
.
Tôi đang sử dụng một BooleanToVisibilityConverter
WPF để ràng buộc thuộc Visibility
tính của điều khiển với a Boolean
. Điều này hoạt động tốt, nhưng tôi muốn một trong các điều khiển để ẩn nếu boolean là true
, và hiển thị nếu nó false
.
Câu trả lời:
Triển khai IValueConverter của riêng bạn. Một triển khai mẫu là tại
http://msdn.microsoft.com/en-us/l Library / system.windows.data.ivalueconverter.aspx
Trong phương thức Chuyển đổi của bạn, yêu cầu nó trả về các giá trị bạn muốn thay vì mặc định.
Thay vì đảo ngược, bạn có thể đạt được cùng một mục tiêu bằng cách sử dụng IValueConverter
triển khai chung có thể chuyển đổi giá trị Boolean thành giá trị đích có thể định cấu hình thành đúng và sai. Dưới đây là một trong những thực hiện như vậy:
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);
}
}
Tiếp theo, phân lớp nó ở đâu T
là Visibility
:
public sealed class BooleanToVisibilityConverter : BooleanConverter<Visibility>
{
public BooleanToVisibilityConverter() :
base(Visibility.Visible, Visibility.Collapsed) {}
}
Cuối cùng, đây là cách bạn có thể sử dụng BooleanToVisibilityConverter
ở trên trong XAML và định cấu hình nó, ví dụ, sử dụng Collapsed
cho đúng và Visible
sai:
<Application.Resources>
<app:BooleanToVisibilityConverter
x:Key="BooleanToVisibilityConverter"
True="Collapsed"
False="Visible" />
</Application.Resources>
Sự đảo ngược này rất hữu ích khi bạn muốn liên kết với một thuộc tính Boolean có tên IsHidden
là trái ngược IsVisible
.
Visibility
các thuộc tính trong mô hình quan điểm của bạn.
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;
}
}
và sau đó chuyển đúng hoặc sai dưới dạng ConverterParameter
<Grid.Visibility>
<Binding Path="IsYesNoButtonSetVisible" Converter="{StaticResource booleanToVisibilityConverter}" ConverterParameter="true"/>
</Grid.Visibility>
else if (value is bool?)
phần mình, ReSharper nói với tôi "Biểu hiện luôn luôn sai". Ngoài ra, if (flag)
phần có thể được viết lại chính xác hơn như return flag ? Visibility.Visible : Visibility.Collapsed;
.
var nullable = (bool?)value; flag = nullable.GetValueOrDefault();
có thể được thực hiện ngắn hơn và đơn giản hơn:flag = (bool?)value ?? false;
Viết của riêng bạn là giải pháp tốt nhất cho bây giờ. Dưới đây là một ví dụ về Trình chuyển đổi có thể thực hiện cả hai cách Bình thường và Đảo ngược. Nếu bạn có bất kỳ vấn đề với điều này chỉ cần hỏi.
[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
bằng cách kiểm tra tham số cho null:Parameter direction = Parameter.Normal; if (parameter != null) direction = (Parameter)Enum.Parse(typeof(Parameter), (string)parameter);
Ngoài ra còn có dự án WPF Converters trên Codeplex. Trong tài liệu của họ, họ nói rằng bạn có thể sử dụng MapConverter của họ để chuyển đổi từ bảng liệt kê Hiển thị sang 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>
Một cách nữa để Bind ViewModel Giá trị Boolean (IsButtonVisible) với thuộc tính Hiển thị kiểm soát xaml. Không mã hóa, Không chuyển đổi, chỉ cần tạo kiểu.
<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>
Hoặc cách lười biếng thực sự, chỉ cần tận dụng những gì đã có và lật nó:
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;
}
}
Nếu bạn không thích viết trình chuyển đổi tùy chỉnh, bạn có thể sử dụng trình kích hoạt dữ liệu để giải quyết vấn đề này:
<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>
Tôi vừa làm một bài về điều này. Tôi đã sử dụng một ý tưởng tương tự như Michael Hohlios đã làm. Chỉ, tôi đã sử dụng Thuộc tính thay vì sử dụng "tham số đối tượng".
Khả năng hiển thị liên kết với giá trị bool trong WPF
bằng cách sử dụng thuộc tính làm cho nó dễ đọc hơn, theo ý kiến của tôi.
<local:BoolToVisibleOrHidden x:Key="BoolToVisConverter" Collapse="True" Reverse="True" />
Đây là một cái tôi đã viết và sử dụng rất nhiều. Nó sử dụng tham số chuyển đổi boolean cho biết có đảo ngược giá trị hay không và sau đó sử dụng XOR để thực hiện phủ định:
[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;
}
}
Đây là bảng chân lý XOR để tham khảo:
XOR
x y XOR
---------
0 0 0
0 1 1
1 0 1
1 1 0
Tôi đang tìm kiếm một câu trả lời tổng quát hơn, nhưng không thể tìm thấy nó. Tôi đã viết một công cụ chuyển đổi có thể giúp đỡ người khác.
Nó dựa trên thực tế là chúng ta cần phân biệt sáu trường hợp khác nhau:
Đây là cách thực hiện của tôi cho 4 trường hợp đầu tiên:
[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();
}
}
thí dụ:
Visibility="{Binding HasItems, Converter={StaticResource BooleanToVisibilityConverter}, ConverterParameter='t2v_f2c'}"
Tôi nghĩ rằng các thông số là dễ nhớ.
Hy vọng nó sẽ giúp được ai đó.
Bạn có thể sử dụng QuickConverter .
Với QuickConverter, bạn có thể viết nội tuyến logic chuyển đổi bằng BindingExpression của bạn
Đây là một trình chuyển đổi BooleanToVisibility ngược:
Visibility="{qc:Binding '!$P ? Visibility.Visible : Visibility.Collapsed', P={Binding Example}}"
Bạn có thể thêm QuickConverter qua NuGet. Có một cái nhìn vào các tài liệu để thiết lập. Liên kết: https://quickconverter.codeplex.com/
Một phiên bản một cách đơn giản có thể được sử dụng như thế này:
Visibility="{Binding IsHidden, Converter={x:Static Ui:Converters.BooleanToVisibility}, ConverterParameter=true}
có thể được thực hiện như thế này:
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();
}
}
Chuyển đổi mọi thứ thành mọi thứ (bool, chuỗi, enum, v.v.):
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;
}
}
Ví dụ về 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>
Thay vì viết mã / phát minh lại của riêng bạn, hãy xem xét sử dụng 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 cũng khá hữu ích cho nhiều tình huống khác.
Tôi biết đây là ngày, nhưng, bạn không cần phải thực hiện lại bất cứ điều gì.
Những gì tôi đã làm là phủ nhận giá trị trên tài sản như thế này:
<!-- 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); }
}
Và nó hoạt động tốt!
Tui bỏ lỡ điều gì vậy?