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

在需要驗證的屬性前加上特性即可

運行結果:

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM