C# 在XAML中的布尔值到复选框状态转换器中返回null
我有一个TaskStatus到Boolean转换器,它在XAML中为Windows应用商店应用程序(通用应用程序)实现IValueConverter接口 我有三种任务状态,我使用IsThrestate=“true”在复选框中启用了不确定状态 现在,尽管IsChecked属性似乎是一个Boolean?,但转换器始终将System.Boolean作为目标类型。无论我返回什么(例如null),都会转换为false,因此我无法在复选框中获取第三个状态 有没有一种方法可以在我的转换器中指定TargetType,或者返回null,以便IsChecked得到null作为输入,从而显示第三种状态 以下是转换器:C# 在XAML中的布尔值到复选框状态转换器中返回null,c#,xaml,checkbox,windows-store-apps,win-universal-app,C#,Xaml,Checkbox,Windows Store Apps,Win Universal App,我有一个TaskStatus到Boolean转换器,它在XAML中为Windows应用商店应用程序(通用应用程序)实现IValueConverter接口 我有三种任务状态,我使用IsThrestate=“true”在复选框中启用了不确定状态 现在,尽管IsChecked属性似乎是一个Boolean?,但转换器始终将System.Boolean作为目标类型。无论我返回什么(例如null),都会转换为false,因此我无法在复选框中获取第三个状态 有没有一种方法可以在我的转换器中指定TargetTy
public class TaskStatusToCheckBoxStateConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string language)
{
var taskStatus = (TaskStatus) value;
switch (taskStatus)
{
case TaskStatus.Open:
return false;
case TaskStatus.InProgress:
return null;
case TaskStatus.Done:
return true;
default:
throw new ArgumentOutOfRangeException();
}
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
var checkBoxState = (Boolean?) value;
if (checkBoxState == null)
return TaskStatus.InProgress;
if (checkBoxState.Value)
return TaskStatus.Done;
return TaskStatus.Open;
}
}
复选框的XAML代码
<CheckBox x:Name="CheckBoxTaskState"
IsThreeState="True"
IsChecked="{Binding Status,
Converter={StaticResource TaskStatusToCheckBoxStateConverter},
Mode=TwoWay}">
</CheckBox>
根据[this][1]:目前不支持绑定到WinRT中的可空类型。这对于一个无文件记录的规则来说怎么样?现在你知道了 从这个开始
public sealed partial class MainPage : Page, INotifyPropertyChanged
{
public MainPage()
{
this.InitializeComponent();
this.DataContext = this;
}
private void NullButton_Click(object sender, RoutedEventArgs e)
{ this.State = null; }
private void FalseButton_Click(object sender, RoutedEventArgs e)
{ this.State = false; }
private void TrueButton_Click(object sender, RoutedEventArgs e)
{ this.State = true; }
bool? _State = null;
public bool? State { get { return _State; } set { SetProperty(ref _State, value); } }
public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
void SetProperty<T>(ref T storage, T value, [System.Runtime.CompilerServices.CallerMemberName] String propertyName = null)
{
if (!object.Equals(storage, value))
{
storage = value;
if (PropertyChanged != null)
PropertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));
}
}
}
您的XAML将仅更改如下:
<CheckBox Content="Hello three-state"
IsThreeState="True"
local:NullableCheckbox.Enabled="true"
local:NullableCheckbox.IsChecked="{Binding State, Mode=TwoWay}" />
常规IsChecked属性不重要,它将被附加属性覆盖。您的viewmodel可以保持不变。真的很神奇,是吗
祝你好运 尝试返回可为null的
而不是仅为null。(请注意,Nullable是一个结构,它将作为一个对象装箱。因此,返回null与返回Nullable并不相同。)也不起作用。不幸的是,同样的结果。也许我做错了。我现在已经返回新的Nullable()代码>。这就是你的意思吗?我刚刚选中了tri-state复选框和System.Windows.Data.IValueConverter(手头没有VS2013/WindowsStore项目),其Convert方法返回null或new Nullable。这两种变体都很有魅力。您是否尝试在Convert和ConvertBack方法中设置断点,以观察绑定和转换器正在处理哪些值?是的。我查过了。当值为TaskStatus.InProgress时,代码将正确进入相应的开关盒。目标类型始终为System.Boolean。ConvertBack很有魅力。Just Convert不会返回正确的空值。我也在WPF应用程序中尝试了同样的方法,就像在您这边一样,它可以按预期工作(null和null)。我不相信WindowsStore应用程序中的复选框或转换器绑定被破坏。如果您看到ConvertBack正常工作,而Convert似乎不工作,那么我只能想到以下可能导致您出现问题的场景:(1)在代码背后的某个地方,或者作为XAML中触发器定义的一部分,CheckBox属性的值IsChecked或IsThrestate在某些情况下发生更改。(2) 您的代码还有另一个双向数据绑定,IsChecked或IsThreeState属性作为其绑定源,从而更改属性。
public class NullableCheckbox : DependencyObject
{
public static bool GetEnabled(DependencyObject obj)
{ return (bool)obj.GetValue(EnabledProperty); }
public static void SetEnabled(DependencyObject obj, bool value)
{ obj.SetValue(EnabledProperty, value); }
public static readonly DependencyProperty EnabledProperty =
DependencyProperty.RegisterAttached("Enabled", typeof(bool), typeof(NullableCheckbox), new PropertyMetadata(false, EnabledChanged));
private static void EnabledChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var checkbox = d as CheckBox;
if ((bool)e.NewValue)
{
var binding = new Binding
{
Path = new PropertyPath("IsChecked"),
Mode = BindingMode.TwoWay,
Source = checkbox,
};
checkbox.SetBinding(NullableCheckbox.InternalStateProperty, binding);
}
}
private static object GetInternalState(DependencyObject obj)
{ return (object)obj.GetValue(InternalStateProperty); }
private static void SetInternalState(DependencyObject obj, object value)
{ obj.SetValue(InternalStateProperty, value); }
private static readonly DependencyProperty InternalStateProperty =
DependencyProperty.RegisterAttached("InternalState", typeof(object),
typeof(NullableCheckbox), new PropertyMetadata(null, InternalStateChanged));
private static void InternalStateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{ SetIsChecked(d, (object)e.NewValue); }
public static object GetIsChecked(DependencyObject obj)
{ return (object)obj.GetValue(IsCheckedProperty); }
public static void SetIsChecked(DependencyObject obj, object value)
{ obj.SetValue(IsCheckedProperty, value); }
public static readonly DependencyProperty IsCheckedProperty =
DependencyProperty.RegisterAttached("IsChecked", typeof(object),
typeof(NullableCheckbox), new PropertyMetadata(default(object), IsCheckedChanged));
private static void IsCheckedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var checkbox = d as CheckBox;
bool? newvalue = null;
if (e.NewValue is bool?)
newvalue = (bool?)e.NewValue;
else if (e.NewValue != null)
{
bool newbool;
if (!bool.TryParse(e.NewValue.ToString(), out newbool))
return;
newvalue = newbool;
}
if (!checkbox.IsChecked.Equals(newvalue))
checkbox.IsChecked = newvalue;
}
}
<CheckBox Content="Hello three-state"
IsThreeState="True"
local:NullableCheckbox.Enabled="true"
local:NullableCheckbox.IsChecked="{Binding State, Mode=TwoWay}" />