• WPF 数据验证


    Validation ValidationRule iDataErrorInfo+DataAnimation 的用法

    //Validation:依赖属性用(在验证回调中返回false)

    //ValidationRule:依赖属性和普通类的属性都能用
    //IdataErrorInfo:依赖属性和普通类的属性都能用,谁想用的话 就继承iDataErrorInfo

    区别?

    ValidationRule可以自定义错误信息,Validation和ValidationRule在xaml中的用法一样,比较繁琐

    iDataErrorErrorInfo可以使用属性索引器,在xaml中只需咋binding表达式中打开ValidatesOnDataErrors=True即可,xaml代码比较少

    ValidationRule和iDataErrorInfo的错误信息都是被全局静态对象Validation接收的

    1.Validation 依赖属性的验证

    界面上有2个控件,一个textbox绑定一个自定义的依赖属性,一个textblock绑定前面依赖属性的验证结果

    依赖属性都有一个private static bool ValidateValueCallback(object value)验证回调函数,返回值是验证的结果bool类型的,value是依赖属性的数据,在验证回调中做一下判断,当不满足条件时,返回一个false,

    这时候全局静态对象Validation就能捕获到这个验证结果

    <TextBox Name="tb">
      <TextBox.Text>
         <Binding Path="MyProperty" UpdateSourceTrigger="PropertyChanged">
          <Binding.ValidationRules>
            <ExceptionValidationRule/>
          </Binding.ValidationRules>
        </Binding>
      </TextBox.Text>
    </TextBox>
    <TextBox Text="{Binding Path=(Validation.Errors)[0].ErrorContent,ElementName=tb}"/>-->

    在依赖属性的验证回调中判断,

    运行结果

     2.ValidationRule 依赖属性的验证

    上面的验证信息(“123456”不是属性“Myproperty”的有效值)是由ExceptionValidationRule默认提供的错误提示消息

     错误信息能不能自定义呢?这时候要自己写一个ValidationRule

    可以看到ExceptionValidationRule也是继承自ValidationRule的

    新建一个类继承自ValidationRule,重写ValidationResult

     那怎么用自己定义的去代替ExceptionValidationRule?

    运行结果:

     

     3.iDataErrorInfo和DataAnnotations特性

    普通属性所在的类继承iDataErrorInfo,并实现iDataErrorInfo提供的接口和索引器

     public class Person : INotifyPropertyChanged, IDataErrorInfo
        {
            private int _id;
            private string _name;
    
            public string Name
            {
                get { return _name; }
                set { _name = value;
                    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Name"));
                }
            }
    
            public int ID
            {
                get { return _id; }
                set { _id = value;
                    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("ID"));
                }
            }
    
            //INotifyPropertyChanged的接口
            public event PropertyChangedEventHandler? PropertyChanged;
            //IDataErrorInfo的接口
            public string Error { get { return ""; } }
    
            public string this[string columnName]
            {
                get
                {
                     if (columnName == "ID")
                    {
                           if (_id >18)
                        {
                            return ">18";
                        }
                    }
    
                     if (columnName == "Name")
                    {
                        if (Name.Length > 3)
                            return "leng>3";
                    }
    
                     return string.Empty;
                }
            }
        }

    Person类提供了2个属性,继承了iDataErrorInfo,在索引器中判断每个属性的值是否符合要求,在索引器中的return 返回的值会被全局静态对象Validation接受,这是binding表达式提供的功能,会在绑定的目标和数据源之间检测是否存在检验信息,在控件上如何获取呢?

    只需要在需要接受验证的对象上打开

    ValidatesOnDataErrors=True,ValidatesOnExceptions=True

    xaml代码:

    <Grid>
            <StackPanel>
                <Label Content="ID"/>
                <TextBox x:Name="tb" Text="{Binding ID, UpdateSourceTrigger=PropertyChanged,Mode=TwoWay,ValidatesOnDataErrors=True,ValidatesOnExceptions=True}"/>
                <TextBox Text="{Binding Path=(Validation.Errors)[0].ErrorContent,ElementName=tb}"/>
                <Label Content="Name"/>
                <TextBox x:Name="tbname" Text="{Binding Name,UpdateSourceTrigger=PropertyChanged,Mode=TwoWay,ValidatesOnDataErrors=True,ValidatesOnExceptions=True}"/>
                <TextBox Text="{Binding Path=(Validation.Errors)[0].ErrorContent,ElementName=tbname}"/>
            </StackPanel>
        </Grid>

    运行结果:

     当使用IdataErrorInfo时,需要在索引器中以此判断每个属性和属性的值,为了简化索引器中的代码,通过反射去获取每个属性,并通过添加特性的方法去完成验证

     public class Person : INotifyPropertyChanged, IDataErrorInfo
        {
            private int _id;
            private string _name;
            [Required]
            [MyArrtibute ]
            public string Name
            {
                get { return _name; }
                set
                {
                    _name = value;
                    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Name"));
                }
            }
            [Range(0,18,ErrorMessage ="超出范围了")]
            [Required]
            public int ID
            {
                get { return _id; }
                set
                {
                    _id = value;
                    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("ID"));
                }
            }
    
            //INotifyPropertyChanged的接口
            public event PropertyChangedEventHandler? PropertyChanged;
            //IDataErrorInfo的接口
            public string Error { get { return ""; } }
            public string this[string columnName]
            {
                get
                {
                    //引入命名空间using System.ComponentModel.DataAnnotations;
                    var vc = new ValidationContext(this, null, null);
                    vc.MemberName = columnName;
                    var res = new List<ValidationResult>();
                    var result = Validator.TryValidateProperty(this.GetType().GetProperty(columnName).GetValue(this, null), vc, res);
                    if (res.Count > 0)
                    {
                        return string.Join(Environment.NewLine, res.Select(r => r.ErrorMessage).ToArray());
                    }
                    return string.Empty;
                }
            }
        }

    一个类继承了IdataErrorInfi后,又使用DataAnnotations去改善索引器后,属性的验证逻辑需要通过特性的方式去完成,特性分为系统自带的和自定义的,新建特性的方法,新建一个类并继承ValidationAttribute,在该类中返回一个ValidationResult即可。

    新建特性代码:

    public class MyArrtibute : ValidationAttribute
        {
            protected override ValidationResult? IsValid(object? value, ValidationContext validationContext)
            {
                if (value.ToString().Length > 10)
                    return new ValidationResult("名字长度大于10了");
    
                return base.IsValid(value, validationContext);
            }
        }

    第一个参数value就是在binding表达式,从数据源到目标的值,这里的return返回的值依旧是被全局静态对象Validation接受,这是由binding功能提供的

    特性的使用方法:

        [Required]
            [MyArrtibute ]
            public string Name
            {
                get { return _name; }
                set
                {
                    _name = value;
                    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Name"));
                }
            }

    在需要验证的属性前加上特性即可

    运行结果:

  • 相关阅读:
    特别实用的 6 款 Python 特殊文本格式处理库推荐
    小白版Python环境搭建,还不会你就掐死小编吧(建议收藏)
    Python抓取网页数据的终极办法
    Neo4j CQL -(17)- NULL值
    Neo4j CQL -(16)- 合并
    Neo4j CQL -(15)- LIMIT和SKIP子句
    Neo4j CQL -(14) -UNION联合
    Neo4j CQL
    Neo4j CQL
    Neo4j CQL
  • 原文地址:https://www.cnblogs.com/1024E/p/15744305.html
Copyright © 2020-2023  润新知