WPF中使用Data Annotations验证Model

简介: 原文:WPF中使用Data Annotations验证Model.NET Framework中System.ComponentModel.DataAnnotations提供了很多属性来验证对象的属性。
原文: WPF中使用Data Annotations验证Model

.NET Framework中System.ComponentModel.DataAnnotations提供了很多属性来验证对象的属性。可以在C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\{.NET Version}\路径下面找到System.ComponentModel.DataAnnotations.dll

public class User
{
    [Required]
    [StringLength(20)]
    public string Name { get; set; }

    [Range(1,120)]
    public int Age { get; set; }
}

检查一个实例是否合法有效,使用下面的代码,具体可以参考: https://msdn.microsoft.com/en-us/library/dd411772%28v=vs.110%29.aspx

Validator.TryValidateObject(obj,new ValidationContext(obj),results,true);
static void Main(string[] args)
{
    ICollection<ValidationResult> results = null;

    User invalidUser = new User
    {
        Name = "My name is System.ComponentModel.DataAnnotations",
        Age = -1,
    };

    if(!Validate(invalidUser, out results))
    {
        Console.WriteLine(string.Join("\n", results.Select(o=>o.ErrorMessage)));
    }
    else
    {
        Console.WriteLine("I am a valid object.");
    }

    Console.ReadKey();
}

static bool Validate<T>(T obj, out ICollection<ValidationResult> results)
{
    results = new List<ValidationResult>();

    return Validator.TryValidateObject(obj, new ValidationContext(obj), results, true);
}

代码中实例化了一个非法的User,代码执行结果如下:

这些ErrorMessage是.NET提供的,如果需要自定义错误信息可以在Attribute上增加ErrorMessage,代码如下:

public class User
{
    [Required]
    [StringLength(20, ErrorMessage ="Out of range~")]
    public string Name { get; set; }

    [Range(1,120, ErrorMessage ="Not a valid age.")]
    public int Age { get; set; }
}

执行结果如下:

如果将User的属性修改为合法的值,结果如下:

User validUser = new User
{
    Name = "Hellen",
    Age = 18,
};

在WPF中,继承IDataErrorInfo接口,通过IDataErrorInfo来传递Data Annotation的ErrorMessage。

class PropertyValidateModel : IDataErrorInfo
{
    public string this[string columnName]
    {
        get
        {
            List<ValidationResult> validationResults = new List<ValidationResult>();

            bool result = Validator.TryValidateProperty(
                GetType().GetProperty(columnName).GetValue(this),
                new ValidationContext(this)
                {
                    MemberName = columnName
                },
                validationResults);

            if (result)
                return null;

            return validationResults.First().ErrorMessage;
        }
    }

    public string Error
    {
        get
        {
            return null;
        }
    }
}

这里只验证单个属性,下面是Model类,注意:Model需要继承INotifyPropertyChanged接口,直接看代码,

class User : PropertyValidateModel, INotifyPropertyChanged
{
    private string _name = string.Empty;

    private int _age = 0;

    [Required]
    [StringLength(20)]
    public string Name
    {
        get
        {
            return _name;
        }
        set
        {
            if(_name != value)
            {
                _name = value;

                RaisePropertyChanged("Name");
            }
        }
    }

    [Required]
    [Range(1,120)]
    public int Age
    {
        get
        {
            return _age;
        }
        set
        {
            if(_age != value)
            {
                _age = value;

                RaisePropertyChanged("Age");
            }
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void RaisePropertyChanged(string propertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

下面看一下UI这一块的ErrorMessage绑定

<StackPanel>
    <TextBlock Text="Name: "/>
    <TextBox Text="{Binding User.Name,UpdateSourceTrigger=PropertyChanged, NotifyOnValidationError=True, ValidatesOnDataErrors=True}" Margin="0,10">
        <Validation.ErrorTemplate>
            <ControlTemplate>
                <StackPanel>
                    <AdornedElementPlaceholder x:Name="textBox" />
                    <TextBlock Text="{Binding [0].ErrorContent}" Foreground="Red"/>
                </StackPanel>
            </ControlTemplate>
        </Validation.ErrorTemplate>
    </TextBox>
    <TextBlock Text="Age" />
    <TextBox Text="{Binding User.Age, UpdateSourceTrigger=LostFocus, NotifyOnValidationError=True, ValidatesOnDataErrors=True}" Margin="0,10">
        <Validation.ErrorTemplate>
            <ControlTemplate>
                <StackPanel>
                    <AdornedElementPlaceholder x:Name="textBox" />
                    <TextBlock Text="{Binding [0].ErrorContent}" Foreground="Red"/>
                </StackPanel>
            </ControlTemplate>
        </Validation.ErrorTemplate>
    </TextBox>
</StackPanel>

运行结果如下:

补充一个内容:

如何自定义一个ValidationAttribute。只需要继承ValidationAttribute,并重写IsValid方法即可。例如:

    public class DivisibleBy7Attribute : ValidationAttribute
    {
        public DivisibleBy7Attribute()
            :base("{0} value is not divisible by 7")
        {
        }

        protected override ValidationResult IsValid(
            object value, 
            ValidationContext validationContext)
        {
            decimal val = (decimal)value;

            bool vaild = val % 7 == 0;

            if (vaild)
                return null;
            return new ValidationResult(base.FormatErrorMessage(validationContext.MemberName));
        }
    }

感谢您的阅读!代码点击这里下载。

目录
相关文章
|
C#
WPF TextBox 正则验证 大于等于0 小于等于1 的两位小数
原文:WPF TextBox 正则验证 大于等于0 小于等于1 的两位小数 正则:^(0\.\d+|[1-9][0-9]|1)$ TextBox绑定正则验证                                                                ...
1397 0
|
C#
WPF QuickStart系列之线程模型(Thread Model)
原文:WPF QuickStart系列之线程模型(Thread Model) 这篇博客将介绍WPF中的线程模型。 首先我们先来看一个例子,用来计算一定范围内的素数个数。 XAML: ...
1046 0
|
C#
WPF QuickStart系列之数据绑定(Data Binding)
原文:WPF QuickStart系列之数据绑定(Data Binding) 这篇博客将展示WPF DataBinding的内容。 首先看一下WPF Data Binding的概览, Binding Source可以是任意的CLR对象,或者XML文件等,Binding Target需要有依赖属性。
1172 0
|
C# 虚拟化 容器
[WPF]WPF Data Virtualization和UI Virtualization
原文:[WPF]WPF Data Virtualization和UI Virtualization 这篇博客将介绍WPF中的虚拟化技术。 1. Data Virtualization 通常情况下我们说数据虚拟化是指数据源没有完全加载,仅加载当前需要显示的数据呈现给用户。
1486 0
|
C#
理解和使用WPF 验证机制
原文:理解和使用WPF 验证机制 首先建立一个demo用以学习和实验WPF Data Validation机制。
1116 0
|
C#
WPF 3D model - Sphere, Cone, and Cylinder
原文:WPF 3D model - Sphere, Cone, and Cylinder   Extending Visual3D - Sphere, Cone, and Cylinder http://blogs.
1031 0
|
C# 数据安全/隐私保护
用WPF写一个登录界面,我想在输入完密码后按回车就能够验证登陆,而不需要用鼠标单击登陆按钮
原文:用WPF写一个登录界面,我想在输入完密码后按回车就能够验证登陆,而不需要用鼠标单击登陆按钮 在wpf中,将按钮的IsDefault设置为true ​​​​
1167 0
|
前端开发 C#
WPF MVVM 架构 Step By Step(6)(把actions从view model解耦)
原文:WPF MVVM 架构 Step By Step(6)(把actions从view model解耦)   到现在为止,我们创建了一个简单的MVVM的例子,包含了实现了的属性和命令。我们现在有这样一个包含了例如textbox类似的输入元素的视图,textbox用绑定来和view model联系,像点击button这样的行为用命令来联系。
1485 0