【问题标题】:What's the order of execution in property setters when using IDataErrorInfo?使用 IDataErrorInfo 时属性设置器中的执行顺序是什么?
【发布时间】:2011-02-08 16:25:51
【问题描述】:

情况:在 WPF 中,我们多次使用 INotifyPropertyChangedIDataErrorInfo 来对我们的数据对象启用绑定和验证。我有很多看起来像这样的属性:

public SomeObject SomeData
{
    get { return _SomeData; }
    set { _SomeData = value; OnPropertyChanged("SomeData"); }
}

当然,我的班级中有一个适当的覆盖 IDataErrorInfo.this[] 来进行验证。

问题:在绑定情况下,验证代码何时执行?什么时候设置属性?什么时候执行setter代码?如果验证失败怎么办?

例如:

  1. 用户输入新数据。
  2. 绑定将数据写入属性。
  3. 属性set方法被执行。
  4. 绑定检查 this[] 以进行验证。
  5. 如果数据无效,绑定会将属性设置回旧值。
  6. 再次执行属性set方法。

如果您在 set 方法中添加“钩子”,这一点很重要,例如:

public string PathToFile
{
    get { return _PathToFile; }
    set
    {
        if (_PathToFile != value &&      // prevent unnecessary actions
            OnPathToFileChanging(value)) // allow subclasses to do something or stop the setter
        {
            _PathToFile = value;
            OnPathToFileChanged();  // allow subclasses to do something afterwards
            OnPropertyChanged("PathToFile");
        }
    }
}

【问题讨论】:

    标签: c# wpf validation data-binding properties


    【解决方案1】:

    如果您想对验证时间进行细粒度控制,您可以:

    private Dictionary<string, string> Errors = new Dictionary<string, string>();
    
    private object _MyProperty;
    
    public object MyProperty
    {
       get { return _MyProperty; }
       set
       {
          Errors["MyProperty"] = null;
          if (value == _MyProperty)
          {
             return;
          }
          ValidateMyProperty(value);  // may set Errors["MyProperty"]
          if (Errors["MyProperty"] == null)
          {
             _MyProperty = value;
             OnPropertyChanged("MyProperty");
          }
       }
    }
    
    public string this[string propertyName]
    {
       return Errors[propertyName];
    }
    

    无论何时请求数据错误信息以及请求者是谁,它始终返回截至上次尝试设置属性时的属性验证状态。

    请注意,如果您使用它,您可以这样封装逻辑:

    public object MyProperty
    {
       set { _MyProperty = Validate("MyProperty", value, _MyProperty); }
    }
    
    private Dictionary<string, Func<object, string>> ValidationFunctions;
    
    private object Validate(string propertyName, object value, object field)
    {
       Errors[propertyName] = null;
       if (value == field)
       {
          return;
       }
       if (!ValidationFunctions.ContainsKey(propertyName))
       {
          return value;
       }
       Errors[propertyName] = ValidationFunctions[propertyName](value);
       return (Errors[propertyName] == null) 
          ? value 
          : field;
       }
    }
    

    【讨论】:

    • 感谢您花时间想出这种控制验证的方式。这是您在实际程序中使用过的东西吗?
    • 是的,但由于某些特定于我的应用程序的原因,我的逻辑比上述要复杂得多。
    猜你喜欢
    • 2015-09-06
    • 2015-02-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-27
    • 2011-05-14
    • 2012-07-13
    相关资源
    最近更新 更多