zoukankan      html  css  js  c++  java
  • WPF中使用Data Annotations验证Model

    .NET Framework中System.ComponentModel.DataAnnotations提供了很多属性来验证对象的属性。可以在C:Program Files (x86)Reference AssembliesMicrosoftFramework.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("
    ", 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));
            }
        }

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

  • 相关阅读:
    机器学习
    机器学习
    JavaWeb之tomcat安装、配置与使用(一)
    Tomcat安装、配置和部署笔记
    Java配置----JDK开发环境搭建及环境变量配置
    安装SQL2012
    SQLServer 数据库变成单个用户后无法访问问题的解决方法
    临时记录
    SQL Server 动态生成数据库所有表Insert语句
    SQL2000查看表的大小
  • 原文地址:https://www.cnblogs.com/yang-fei/p/7372535.html
Copyright © 2011-2022 走看看