8

如何使用 IValueConverter 将空值转换为布尔值?

我正在使用 wpf 尝试显示一堆布尔值(在复选框中)。创建新记录时,这些值为空,并在复选框中显示为“不确定”。我希望空值出现并保存为“假”值。

我试图创建一个 NullToBoolean 转换器,它从数据库中获取空值并将它们显示为 false,然后在用户点击保存时将它们保存为 false。(本质上,我试图避免用户必须在复选框中单击两次(一次使其为真,然后再次使其为假)。这似乎适用于导入 - 即空值显示为假 - 但除非我做了两次点击跳舞,保存时数据库中的值不会改变。

我的转换器:

[ValueConversion(typeof(bool), typeof(bool))]
public class NullBooleanConverter : IValueConverter
{

  public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
  {
    if (value != null)
    {
      return value;
    }
    return false;
  }

  public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
  {
    if (value != null)
    {
      return value;
    }
    return null;
  }
}

我试图让转换器使用的复选框之一:

    <CheckBox Grid.Column="1" Grid.Row="0" Padding="5" Margin="5" VerticalAlignment="Center" Name="chkVarianceDescriptionProvided" IsThreeState="False">
      <CheckBox.IsChecked>
        <Binding Path="VarianceDescriptionProvided" Mode="TwoWay">
          <Binding.Converter>
            <utils:NullBooleanConverter />
          </Binding.Converter>
        </Binding>
      </CheckBox.IsChecked>
    </CheckBox>

我不知道问题是因为我的代码错误,还是转换器认为没有任何改变,因此不需要ConvertBack. 我已经尝试了Mode使用 ConvertBack 进行转换的所有 s 和切换代码,但似乎没有任何效果。

有人可以指出我需要做些什么来解决这个问题吗?

4

3 回答 3

22

嗯,如果可以开箱即用,为什么要使用转换器?

<CheckBox IsChecked="{Binding VarianceDescriptionProvided, TargetNullValue=False}" />

有关更多信息,请查看此处

于 2013-03-12T10:47:07.477 回答
1

真正的问题是您一开始并没有初始化数据对象。不要“修复”,从一开始就做好;建设者很好(例如)。您还应该制作 ViewModels/DataModels,而不是直接使用您的模型(数据库等)。

public class MyObjectBuilder
{
     Checked _checked;

     public  MyObjectBuilder()
     {
          Reset()
     }

     private void Reset()
     { 
          _checked = new Checked(true); //etc
     }

     public MyObjectBuilder WithChecked(bool checked)
     {
          _checked = new Checked(checked);
     }

     public MyObject Build()
     {
         var built = new MyObject(){Checked = _checked;} 
         Reset();
         return built;
     }
}

然后始终使用构建器进行初始化

myObjects.Add(new MyObjectBuilder().Build());

或者

myObjects.Add(_injectedBuilder.Build()); // Initialises Checked to default 
myObjects.Add(_injectedBuilder.WithChecked(true).Build()); //True

虽然这不能解决您提出的问题,但它会以您可以单元测试的方式解决您的潜在问题。即您可以测试以确保添加到对象列表中的值始终被初始化。

于 2013-03-12T09:58:38.353 回答
0

只需在执行数据绑定之前更正您的数据。这是唯一的选择。转换器只会使复选框显示为“未选中”并仅在您与控件交互时更新您的数据。例如:

foreach (var item in items)
{
    if (item.VarianceDescriptionProvided == null)
        item.VarianceDescriptionProvided = false;
}
于 2013-03-12T09:56:08.517 回答