如何在属性引发错误时为其设置null值

本文关键字:设置 null 错误 属性 | 更新日期: 2023-09-27 18:21:26

绑定在WPF中非常强大。假设我们有一个Number属性(可以为null的int),并且绑定到一个文本框。

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

我的意思是这些是过程:

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

有没有一种方法可以在绑定产生错误时设置null值?

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

更新:

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

如何在属性引发错误时为其设置null值

您使用的是UpdateSourceTrigger=PropertyChanged,这意味着每当用户按下某个键时,它都会将数据存储在您的数据上下文中

例如,用户键入2,则属性等于"2"。用户键入b,它将尝试用"2b"替换"2",但失败了,因此保留了"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
}

我认为获得该行为的最简单方法是使用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}" ... />

它变得更加强大。您可能应该通过接口/绑定本身进行验证——WPF对此有内置的支持,可以在MSDN上的数据绑定概述中找到示例。

实现这一点的示例如下:

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

链接的文档涵盖了相当多的绑定主题,因此以下是"数据验证"相关部分的摘录:

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

ExceptionValidationRule检查绑定源属性的更新。在前面的例子中,StartPrice的类型为integer。当用户输入的值无法转换为整数,则引发异常,导致要标记为无效的绑定。设置ExceptionValidationRule显式设置ValidatesOnExceptions属性在您的BindingMultiBinding对象。