【问题标题】:How to set a null value to a property when it throws an error?抛出错误时如何将空值设置为属性?
【发布时间】:2012-02-19 17:58:07
【问题描述】:

绑定在 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)

有没有办法让绑定在产生错误时设置一个空值?

有人告诉我我需要实现 IDataErrorInfo,但我猜这个接口是为了验证业务规则。所以我不喜欢使用它。

更新:

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

【问题讨论】:

  • 向我们展示您用于绑定文本框的代码。

标签: c# wpf validation binding validationrules


【解决方案1】:

您正在使用UpdateSourceTrigger=PropertyChanged,这意味着无论何时用户点击一个键,它都会将数据存储在您的数据上下文中

例如,用户键入2,那么您的属性等于"2"。用户输入b,它会尝试用"2b"替换"2",但失败了,所以"2"的原始属性仍然存在。

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

当产生错误时,您可以将属性设置为null,但我不建议这样做,因为如果用户不小心按错键,TextBox 将被清除。

附带说明,使用IDataErrorInfo 进行所有验证,而不仅仅是业务规则验证。 WPF 是为使用它而构建的。我的模型使用它来验证他们的数据是正确的长度、类型等,我的视图模型使用它来验证是否遵循了业务规则

编辑

我的替代建议是绑定到字符串值,而不是数字字段。这样,当值发生变化时,您可以尝试将其强制转换为 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
}

【讨论】:

  • 最后一句话是有道理的。那么,您认为使用转换器之类的东西方便吗?
  • @DarfZon 为了什么?转换器旨在用于将一种数据类型转换为另一种数据类型,因此我看不到您要使用一种数据类型来完成什么。
  • 好吧,有一个疑问。在这种情况下,我该如何使用 IDataErrorInfo,因为如果我手动为 Number 属性设置 null 值,文本框将更新(并且应该显示不正确的值)
  • @DarfZon 像我在回答中建议的那样从绑定中删除UpdateSourceTrigger="PropertyChanged" 是否有效?它将使该属性仅在 TextBox 失去焦点时才更新,这意味着他们完成了输入。
  • 为什么要使用 IDataErrorInfo?
【解决方案2】:

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

【讨论】:

  • 为此,您需要将逻辑放入ConvertBack,因为这是在尝试更新支持绑定的属性时运行的内容,我认为它不会显示验证错误.
  • @Rachel 关于转换方向的观点很好,你是对的:它不会显示验证错误,因为不再有任何验证错误 - 属性上设置的每个值都是有效的。 OP 没有提到验证消息,所以我假设这没问题
  • 我以为他关心验证,因为绑定包含ValidatesOnDataErrors="True",但如果不是这种情况,并且如果他不关心输入无效值时 TextBox 的文本会重置,那么这可能会很好。我想。我想对其进行测试以确定,因为null 是数据对象的有效值,但不是转换器:)
  • @Rachel 是的,它需要空值检查,但我想简洁:)
【解决方案3】:

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

实现此功能的示例如下:

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

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

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

ExceptionValidationRule 检查在运行期间抛出的异常 绑定源属性的更新。在前面的例子中, StartPrice 是整数类型。当用户输入一个值时 不能转换为整数,抛出异常,导致 绑定被标记为无效。设置 ExceptionValidationRule 明确是设置 ValidatesOnExceptions 属性在您的 Binding 上为 true 或 MultiBinding 对象。

【讨论】:

  • 我不知道这对我有什么帮助。我真的在使用带有这个属性的验证规则:ValidatesOnExceptions=True
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-01-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多