WPF中使用Data Annotations驗證Model
阿新 • • 發佈:2018-11-12
原文:
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)); } }
感謝您的閱讀!程式碼點選這裡下載。