使用IDataErrorInfo时,属性设置器中的执行顺序是什么?

时间:2010-04-16 04:17:25

标签: c# wpf validation data-binding properties

情况: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方法。
  7. 如果要在set方法中添加“hooks”,这很重要,例如:

    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");
            }
        }
    }
    

1 个答案:

答案 0 :(得分: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;
   }
}