WPF绑定:对ValidationRules使用DataAnnotations

Phi*_*oie 13 wpf binding validationrules data-annotations

我已经阅读了很多关于WPF验证的博客文章DataAnnotations.我在想,如果有使用干净的方式DataAnnotations作为ValidationRules对我的实体.

所以没有这个(来源):

<Binding Path="Age" Source="{StaticResource ods}" ... >
  <Binding.ValidationRules>
    <c:AgeRangeRule Min="21" Max="130"/>
  </Binding.ValidationRules>
</Binding>
Run Code Online (Sandbox Code Playgroud)

你必须拥有你的

public class AgeRangeRule : ValidationRule 
{...}
Run Code Online (Sandbox Code Playgroud)

我希望WPF Binding能够看到Age属性并查找DataAnnotation,如下所示:

[Range(1, 120)]
public int Age
{
  get { return _age; }
  set
  {
    _age = value;
    RaisePropertyChanged<...>(x => x.Age);
  }
}
Run Code Online (Sandbox Code Playgroud)

任何想法,如果这是可能的?

Phi*_*oie 8

我找到的最接近的方法是:

// This loop into all DataAnnotations and return all errors strings
protected string ValidateProperty(object value, string propertyName)
{
  var info = this.GetType().GetProperty(propertyName);
  IEnumerable<string> errorInfos =
        (from va in info.GetCustomAttributes(true).OfType<ValidationAttribute>()
         where !va.IsValid(value)
         select va.FormatErrorMessage(string.Empty)).ToList();


  if (errorInfos.Count() > 0)
  {
    return errorInfos.FirstOrDefault<string>();
  }
  return null;
Run Code Online (Sandbox Code Playgroud)

资源

public class PersonEntity : IDataErrorInfo
{

    [StringLength(50, MinimumLength = 1, ErrorMessage = "Error Msg.")]
    public string Name
    {
      get { return _name; }
      set
      {
        _name = value;
        PropertyChanged("Name");
      }
    }

public string this[string propertyName]
    {
      get
      {
        if (porpertyName == "Name")
        return ValidateProperty(this.Name, propertyName);
      }
    }
}
Run Code Online (Sandbox Code Playgroud)

来源来源

这样,DataAnnotation工作正常,我在XAML上做了最少的事情ValidatesOnDataErrors="True",这是使用DataAnnotation的Aaron帖子的一个很好的解决方法.

  • 您应该知道,在分配值之前,不会调用IDataErrorInfo的实现.因此,如果另一个对象订阅了DTO的PropertyChanged,那么它们将使用很快可能被您的代码标记为无效的值. (2认同)

Aar*_*ver 5

在你的模型中你可以实现IDataErrorInfo并做这样的事情......

string IDataErrorInfo.this[string columnName]
{
    get
    {
        if (columnName == "Age")
        {
            if (Age < 0 ||
                Age > 120)
            {
                return "You must be between 1 - 120";
            }
        }
        return null;
    }
}
Run Code Online (Sandbox Code Playgroud)

您还需要通知绑定目标新定义的行为.

<TextBox Text="{Binding Age, ValidatesOnDataErrors=True}" />
Run Code Online (Sandbox Code Playgroud)

编辑:

如果您只想使用数据注释,可以关注此博客文章,其中概述了如何完成任务.

更新:

上述链接的历史表示.