如何在抛出错误时为属性设置空值?

时间:2012-01-26 16:32:31

标签: c# wpf validation binding validationrules

绑定在WPF中非常强大。假设我们有一个Number属性(nullable int)并绑定到一个文本框。

我意识到当它抛出错误时,该属性具有最后一个正确的值。

我的意思是这些是过程:

TEXTBOX: ""     PROPERTY: null
TEXTBOX: "2"    PROPERTY: 2
TEXTBOX: "2b"   PROPERTY: 2   <-- here is the problem, should be null instead 2(by the error)

绑定在产生错误时是否设置了空值?

有些人告诉我我需要实现IDataErrorInfo,但我想这个接口是验证业务规则。所以我不喜欢用户。

更新:

    <TextBox Text="{Binding Number, UpdateSourceTrigger=PropertyChanged,
        ValidatesOnExceptions=True, ValidatesOnDataErrors=True,
        NotifyOnValidationError=True, TargetNullValue={x:Static sys:String.Empty}}"

3 个答案:

答案 0 :(得分:3)

您正在使用UpdateSourceTrigger=PropertyChanged,这意味着只要用户点击某个键,它就会将数据存储在您的数据上下文中

例如,用户类型2,则您的属性等于"2"。用户类型b,它会尝试将"2"替换为失败的"2b",因此"2"的原始属性仍然存在。

删除UpdateSourceTrigger,它将恢复为默认值LostFocus,这意味着它只会在TextBox失去焦点时更新属性。

您可以在产生错误时将属性设置为null,但我不建议这样做,因为如果用户意外地点击了错误的密钥,TextBox将被清除。

作为旁注,请使用IDataErrorInfo进行所有验证,而不仅仅是业务规则验证。 WPF是为了与它一起工作而构建的。我的模型使用它来验证他们的数据是否正确长度,类型等,我的ViewModels使用它来验证是否遵循业务规则

修改

我想要的替代建议是绑定到字符串值,而不是数字字段。这样,当值发生变化时,您可以尝试将其强制转换为Int,如果无法转换则返回错误。

public class SomeObject : IDataErrorInfo
{
    public string SomeString { get; set; }
    public Int32? SomeNumber { get; set; }

    #region IDataErrorInfo Members

    public string Error
    {
        get { throw new NotImplementedException(); }
    }

    public string this[string columnName]
    {
        get
        {
            if (columnName == "SomeString")
            {
                int i;
                if (int.TryParse(SomeString, i))
                {
                    SomeNumber = i;
                }
                else
                {
                    SomeNumber = null;
                    return "Value is not a valid number";
                }
            }
            return null;
        }
    }

    #endregion
}

答案 1 :(得分:1)

我认为获得该行为的最简单方法是使用IValueConverterstring转换为int?

public class NullableIntConverter : IValueConverter
{
    public static NullableIntConverter Instance = new NullableIntConverter();
    public void ConvertBack(object value, ...)
    {
        int intValue = 0;
        if (int.TryParse((string)value, out intValue))
            return intValue;

        return null;
    }

    public void Convert(object value, ...)
    {
        return value.ToString();
    }
}

然后你可以在你的绑定中指定这个,如下所示(local映射到你的转换器命名空间):

<TextBox Text="{Binding Number, Converter="{x:Static local:NullableIntConverter.Instance}" ... />

答案 2 :(得分:0)

它变得更强大了。您可能应该通过接口/绑定本身进行验证 - WPF内置了对此的支持,其中的示例可以在Data Binding Overview over at MSDN中找到。

实现这一点的一个例子如下:

<...>
  <Binding.ValidationRules>
    <ExceptionValidationRule />
  </Binding.ValidationRules>
</...>

链接文档涵盖了绑定主题,所以这里是相关部分“数据验证”的摘录:

  

ValidationRule对象检查属性的值是否为   有效的。

     

ExceptionValidationRule检查在此期间抛出的异常   更新绑定源属性。在前面的例子中,   StartPrice的类型为整数。当用户输入一个值时   无法转换为整数,抛出异常,导致   绑定被标记为无效。设置的另一种语法   ExceptionValidationRule显式是设置   ValidatesOnExceptionsBinding属性为MultiBinding   {{1}}对象。