福州网站建设报价,网站建设沈阳凯鸿,小说网站虚拟主机,家教中介网站开发[WPF 基础知识系列] —— 绑定中的数据校验Vaildation 原文:[WPF 基础知识系列] —— 绑定中的数据校验Vaildation前言#xff1a; 只要是有表单存在#xff0c;那么就有可能有对数据的校验需求。如#xff1a;判断是否为整数、判断电子邮件格式等等。 WPF采用一种全新的方式… [WPF 基础知识系列] —— 绑定中的数据校验Vaildation 原文:[WPF 基础知识系列] —— 绑定中的数据校验Vaildation前言 只要是有表单存在那么就有可能有对数据的校验需求。如判断是否为整数、判断电子邮件格式等等。 WPF采用一种全新的方式 - Binding来实现前台显示与后台数据进行交互当然数据校验方式也不一样了。 本专题全面介绍一下WPF中4种Validate方法帮助你了解如何在WPF中对binding的数据进行校验并处理错误显示。 一、简介 正常情况下只要是绑定过程中出现异常或者在converter中出现异常都会造成绑定失败。 但是WPF不会出现任何异常只会显示一片空白当然有些Converter中的异常会造成程序崩溃。 这是因为默认情况下Binding.ValidatesOnException为false所以WPF忽视了这些绑定错误。 但是如果我们把Binding.ValidatesOnException为true那么WPF会对错误做出以下反应 设置绑定元素的附加属性 Validation.HasError为true如TextBox如果Text被绑定并出现错误。创建一个包含错误详细信息如抛出的Exception对象的ValidationError对象。将上面产生的对象添加到绑定对象的Validation.Errors附加属性当中。如果Binding.NotifyOnValidationError是true那么绑定元素的附加属性中的Validation.Error附加事件将被触发。这是一个冒泡事件我们的Binding对象维护着一个ValidationRule的集合当设置ValidatesOnException为true时 默认会添加一个ExceptionValidationRule到这个集合当中。 PS对于绑定的校验只在Binding.Mode 为TwoWay和OneWayToSource才有效 即当需要从target控件将值传到source属性时很容易理解当你的值不需要被别人使用时就很可能校验也没必要。 二、四种实现方法 1、在Setter方法中进行判断 直接在Setter方法中对value进行校验如果不符合规则那么就抛出异常。然后修改XAML不忽视异常。 public class PersonValidateInSetter : ObservableObject{private string name;private int age;public string Name{get { return this.name; }set{if (string.IsNullOrWhiteSpace(value)){throw new ArgumentException(Name cannot be empty!);}if (value.Length 4){throw new ArgumentException(Name must have more than 4 char!);}this.name value;this.OnPropertyChanged(() this.Name);}}public int Age{get{ return this.age; }set{if (value 18){throw new ArgumentException(You must be an adult!);}this.age value;this.OnPropertyChanged(() this.Age);}}} Grid DataContext{Binding PersonValidateInSetter}Grid.RowDefinitionsRowDefinition /RowDefinition //Grid.RowDefinitionsGrid.ColumnDefinitionsColumnDefinition WidthAuto /ColumnDefinition //Grid.ColumnDefinitionsTextBlock TextName: /TextBox Grid.Column1Margin1Text{Binding Name,ValidatesOnExceptionsTrue,UpdateSourceTriggerPropertyChanged} /TextBlock Grid.Row1 TextAge: /TextBox Grid.Row1Grid.Column1Margin1Text{Binding Age,ValidatesOnExceptionsTrue,UpdateSourceTriggerPropertyChanged} //Grid 当输入的值在setter方法中校验时出现错误就会出现一个红色的错误框。 关键代码ValidatesOnExceptionsTrue, UpdateSourceTriggerPropertyChanged。 PS:这种方式有一个BUG首次加载时不会对默认数据进行检验。 2、继承IDataErrorInfo接口 使Model对象继承IDataErrorInfo接口并实现一个索引进行校验。如果索引返回空表示没有错误如果返回不为空 表示有错误。另外一个Erro属性但是在WPF中没有被用到。 public class PersonDerivedFromIDataErrorInfo : ObservableObject, IDataErrorInfo{private string name;private int age;public string Name{get{return this.name;}set{this.name value;this.OnPropertyChanged(() this.Name);}}public int Age{get{return this.age;}set{this.age value;this.OnPropertyChanged(() this.Age);}}// never called by WPFpublic string Error{get{return null;}}public string this[string propertyName]{get{switch (propertyName){case Name:if (string.IsNullOrWhiteSpace(this.Name)){return Name cannot be empty!;}if (this.Name.Length 4){return Name must have more than 4 char!;}break;case Age:if (this.Age 18){return You must be an adult!;}break;}return null;}}} Grid DataContext{Binding PersonDerivedFromIDataErrorInfo}Grid.RowDefinitionsRowDefinition /RowDefinition //Grid.RowDefinitionsGrid.ColumnDefinitionsColumnDefinition WidthAuto /ColumnDefinition //Grid.ColumnDefinitionsTextBlock TextName: /TextBox Grid.Column1Margin1Text{Binding Name,NotifyOnValidationErrorTrue,ValidatesOnDataErrorsTrue,UpdateSourceTriggerPropertyChanged} /TextBlock Grid.Row1 TextAge: /TextBox Grid.Row1Grid.Column1Margin1Text{Binding Age,NotifyOnValidationErrorTrue,ValidatesOnDataErrorsTrue,UpdateSourceTriggerPropertyChanged} / PS这种方式没有了第一种方法的BUG但是相对很麻烦既需要继承接口又需要添加一个索引如果遗留代码那么这种方式就不太好。 3、自定义校验规则 一个数据对象或许不能包含一个应用要求的所有不同验证规则但是通过自定义验证规则就可以解决这个问题。 在需要的地方添加我们创建的规则并进行检测。 通过继承ValidationRule抽象类并实现Validate方法并添加到绑定元素的Binding.ValidationRules中。 public class MinAgeValidation : ValidationRule{public int MinAge { get; set; }public override ValidationResult Validate(object value, CultureInfo cultureInfo){ValidationResult result null;if (value ! null){int age;if (int.TryParse(value.ToString(), out age)){if (age this.MinAge){result new ValidationResult(false, Age must large than this.MinAge.ToString(CultureInfo.InvariantCulture));}}else{result new ValidationResult(false, Age must be a number!);}}else{result new ValidationResult(false, Age must not be null!);}return new ValidationResult(true, null);}} GridGrid.RowDefinitionsRowDefinition /RowDefinition //Grid.RowDefinitionsGrid.ColumnDefinitionsColumnDefinition WidthAuto /ColumnDefinition //Grid.ColumnDefinitionsTextBlock TextName: /TextBox Grid.Column1 Margin1 Text{Binding Name}/TextBoxTextBlock Grid.Row1 TextAge: /TextBox Grid.Row1Grid.Column1Margin1TextBox.TextBinding PathAgeUpdateSourceTriggerPropertyChangedValidatesOnDataErrorsTrueBinding.ValidationRulesvalidations:MinAgeValidation MinAge18 //Binding.ValidationRules/Binding/TextBox.Text/TextBox/Grid 这种方式也会有第一种方法的BUG暂时还不知道如何解决但是这个能够灵活的实现校验并且能传参数。 效果图 4、使用数据注解(特性方式) 在System.ComponentModel.DataAnnotaions命名空间中定义了很多特性 它们可以被放置在属性前面显示验证的具体需要。放置了这些特性之后 属性中的Setter方法就可以使用Validator静态类了来用于验证数据。 public class PersonUseDataAnnotation : ObservableObject{private int age;private string name;[Range(18, 120, ErrorMessage Age must be a positive integer)]public int Age{get{return this.age;}set{this.ValidateProperty(value, Age);this.SetProperty(ref this.age, value, () this.Age);}}[Required(ErrorMessage A name is required)][StringLength(100, MinimumLength 3, ErrorMessage Name must have at least 3 characters)]public string Name{get{return this.name;}set{this.ValidateProperty(value, Name);this.SetProperty(ref this.name, value, () this.Name);}}protected void ValidatePropertyT(T value, string propertyName){Validator.ValidateProperty(value, new ValidationContext(this, null, null) { MemberName propertyName }); } } GridGrid.RowDefinitionsRowDefinition /RowDefinition //Grid.RowDefinitionsGrid.ColumnDefinitionsColumnDefinition WidthAuto /ColumnDefinition //Grid.ColumnDefinitionsTextBlock TextName: /TextBox Grid.Column1Margin1 Text{Binding Name,ValidatesOnExceptionsTrue,UpdateSourceTriggerPropertyChanged} /TextBlock Grid.Row1 TextAge: /TextBox Grid.Row1Grid.Column1Margin1Text{Binding Age,ValidatesOnExceptionsTrue,UpdateSourceTriggerPropertyChanged} //Grid 使用特性的方式能够很自由的使用自定义的规则而且在.Net4.5中新增了很多特性可以很方便的对数据进行校验。 例如EmailAddress, Phone, and Url等。 三、自定义错误显示模板 在上面的例子中我们可以看到当出现验证不正确时绑定控件会被一圈红色错误线包裹住。 这种方式一般不能够正确的展示出错误的原因等信息所以有可能需要自己的错误显示方式。 前面我们已经讲过了。当在检测过程中出现错误时WPF会把错误信息封装为一个ValidationError对象 并添加到Validation.Errors中所以我们可以取出错误详细信息并显示出来。 1、为控件创建ErrorTemplate 下面就是一个简单的例子每次都把错误信息以红色展示在空间上面。这里的AdornedElementPlaceholder相当于 控件的占位符表示控件的真实位置。这个例子是在书上直接拿过来的只能做基本展示用。 ControlTemplate x:KeyErrorTemplateBorder BorderBrushRed BorderThickness2GridAdornedElementPlaceholder x:Name_el /TextBlock Margin0,0,6,0HorizontalAlignmentRightVerticalAlignmentCenterForegroundRedText{Binding [0].ErrorContent} //Grid/Border/ControlTemplate TextBox x:NameAgeTextBoxGrid.Row1Grid.Column1Margin1 Validation.ErrorTemplate{StaticResource ErrorTemplate} 使用方式非常简单将上面的模板作为逻辑资源加入项目中然后像上面一样引用即可。 效果图 对知识梳理总结希望对大家有帮助! posted on 2018-09-21 10:24 NET未来之路 阅读(...) 评论(...) 编辑 收藏 转载于:https://www.cnblogs.com/lonelyxmas/p/9685193.html