日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > asp.net >内容正文

asp.net

[WPF 基础知识系列] —— 绑定中的数据校验Vaildation

發(fā)布時(shí)間:2023/12/13 asp.net 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [WPF 基础知识系列] —— 绑定中的数据校验Vaildation 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
[WPF 基礎(chǔ)知識(shí)系列] —— 綁定中的數(shù)據(jù)校驗(yàn)Vaildation 原文:[WPF 基礎(chǔ)知識(shí)系列] —— 綁定中的數(shù)據(jù)校驗(yàn)Vaildation

前言:

只要是有表單存在,那么就有可能有對(duì)數(shù)據(jù)的校驗(yàn)需求。如:判斷是否為整數(shù)、判斷電子郵件格式等等。

WPF采用一種全新的方式 - Binding,來(lái)實(shí)現(xiàn)前臺(tái)顯示與后臺(tái)數(shù)據(jù)進(jìn)行交互,當(dāng)然數(shù)據(jù)校驗(yàn)方式也不一樣了。

本專題全面介紹一下WPF中4種Validate方法,幫助你了解如何在WPF中對(duì)binding的數(shù)據(jù)進(jìn)行校驗(yàn),并處理錯(cuò)誤顯示。

?

一、簡(jiǎn)介

正常情況下,只要是綁定過(guò)程中出現(xiàn)異常或者在converter中出現(xiàn)異常,都會(huì)造成綁定失敗。

但是WPF不會(huì)出現(xiàn)任何異常,只會(huì)顯示一片空白(當(dāng)然有些Converter中的異常會(huì)造成程序崩潰)。

這是因?yàn)槟J(rèn)情況下,Binding.ValidatesOnException為false,所以WPF忽視了這些綁定錯(cuò)誤。

但是如果我們把Binding.ValidatesOnException為true,那么WPF會(huì)對(duì)錯(cuò)誤做出以下反應(yīng):

  • 設(shè)置綁定元素的附加屬性 Validation.HasError為true(如TextBox,如果Text被綁定,并出現(xiàn)錯(cuò)誤)。
  • 創(chuàng)建一個(gè)包含錯(cuò)誤詳細(xì)信息(如拋出的Exception對(duì)象)的ValidationError對(duì)象。
  • 將上面產(chǎn)生的對(duì)象添加到綁定對(duì)象的Validation.Errors附加屬性當(dāng)中。
  • 如果Binding.NotifyOnValidationError是true,那么綁定元素的附加屬性中的Validation.Error附加事件將被觸發(fā)。(這是一個(gè)冒泡事件)
  • 我們的Binding對(duì)象,維護(hù)著一個(gè)ValidationRule的集合,當(dāng)設(shè)置ValidatesOnException為true時(shí),

    默認(rèn)會(huì)添加一個(gè)ExceptionValidationRule到這個(gè)集合當(dāng)中。

    PS:對(duì)于綁定的校驗(yàn)只在Binding.Mode 為TwoWay和OneWayToSource才有效,

    即當(dāng)需要從target控件將值傳到source屬性時(shí),很容易理解,當(dāng)你的值不需要被別人使用時(shí),就很可能校驗(yàn)也沒(méi)必要。

    ?

    二、四種實(shí)現(xiàn)方法

    1、在Setter方法中進(jìn)行判斷

    直接在Setter方法中,對(duì)value進(jìn)行校驗(yàn),如果不符合規(guī)則,那么就拋出異常。然后修改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.RowDefinitions><RowDefinition /><RowDefinition /></Grid.RowDefinitions><Grid.ColumnDefinitions><ColumnDefinition Width="Auto" /><ColumnDefinition /></Grid.ColumnDefinitions><TextBlock Text="Name:" /><TextBox Grid.Column="1"Margin="1"Text="{Binding Name,ValidatesOnExceptions=True,UpdateSourceTrigger=PropertyChanged}" /><TextBlock Grid.Row="1" Text="Age:" /><TextBox Grid.Row="1"Grid.Column="1"Margin="1"Text="{Binding Age,ValidatesOnExceptions=True,UpdateSourceTrigger=PropertyChanged}" /></Grid>

    ?

    當(dāng)輸入的值,在setter方法中校驗(yàn)時(shí)出現(xiàn)錯(cuò)誤,就會(huì)出現(xiàn)一個(gè)紅色的錯(cuò)誤框。

    關(guān)鍵代碼:ValidatesOnExceptions=True, UpdateSourceTrigger=PropertyChanged。

    PS:這種方式有一個(gè)BUG,首次加載時(shí)不會(huì)對(duì)默認(rèn)數(shù)據(jù)進(jìn)行檢驗(yàn)。

    ?

    2、繼承IDataErrorInfo接口

    使Model對(duì)象繼承IDataErrorInfo接口,并實(shí)現(xiàn)一個(gè)索引進(jìn)行校驗(yàn)。如果索引返回空表示沒(méi)有錯(cuò)誤,如果返回不為空,

    表示有錯(cuò)誤。另外一個(gè)Erro屬性,但是在WPF中沒(méi)有被用到。

    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.RowDefinitions><RowDefinition /><RowDefinition /></Grid.RowDefinitions><Grid.ColumnDefinitions><ColumnDefinition Width="Auto" /><ColumnDefinition /></Grid.ColumnDefinitions><TextBlock Text="Name:" /><TextBox Grid.Column="1"Margin="1"Text="{Binding Name,NotifyOnValidationError=True,ValidatesOnDataErrors=True,UpdateSourceTrigger=PropertyChanged}" /><TextBlock Grid.Row="1" Text="Age:" /><TextBox Grid.Row="1"Grid.Column="1"Margin="1"Text="{Binding Age,NotifyOnValidationError=True,ValidatesOnDataErrors=True,UpdateSourceTrigger=PropertyChanged}" />

    ?

    PS:這種方式,沒(méi)有了第一種方法的BUG,但是相對(duì)很麻煩,既需要繼承接口,又需要添加一個(gè)索引,如果遺留代碼,那么這種方式就不太好。

    ?

    3、自定義校驗(yàn)規(guī)則

    一個(gè)數(shù)據(jù)對(duì)象或許不能包含一個(gè)應(yīng)用要求的所有不同驗(yàn)證規(guī)則,但是通過(guò)自定義驗(yàn)證規(guī)則就可以解決這個(gè)問(wèn)題。

    在需要的地方,添加我們創(chuàng)建的規(guī)則,并進(jìn)行檢測(cè)。

    通過(guò)繼承ValidationRule抽象類,并實(shí)現(xiàn)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);}} <Grid><Grid.RowDefinitions><RowDefinition /><RowDefinition /></Grid.RowDefinitions><Grid.ColumnDefinitions><ColumnDefinition Width="Auto" /><ColumnDefinition /></Grid.ColumnDefinitions><TextBlock Text="Name:" /><TextBox Grid.Column="1" Margin="1" Text="{Binding Name}"></TextBox><TextBlock Grid.Row="1" Text="Age:" /><TextBox Grid.Row="1"Grid.Column="1"Margin="1"><TextBox.Text><Binding Path="Age"UpdateSourceTrigger="PropertyChanged"ValidatesOnDataErrors="True"><Binding.ValidationRules><validations:MinAgeValidation MinAge="18" /></Binding.ValidationRules></Binding></TextBox.Text></TextBox></Grid>

    這種方式,也會(huì)有第一種方法的BUG,暫時(shí)還不知道如何解決,但是這個(gè)能夠靈活的實(shí)現(xiàn)校驗(yàn),并且能傳參數(shù)。

    效果圖:

    ?

    4、使用數(shù)據(jù)注解(特性方式)

    在System.ComponentModel.DataAnnotaions命名空間中定義了很多特性,

    它們可以被放置在屬性前面,顯示驗(yàn)證的具體需要。放置了這些特性之后,

    屬性中的Setter方法就可以使用Validator靜態(tài)類了,來(lái)用于驗(yàn)證數(shù)據(jù)。

    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 ValidateProperty<T>(T value, string propertyName){Validator.ValidateProperty(value,
    new ValidationContext(this, null, null) { MemberName = propertyName });
    }
    } <Grid><Grid.RowDefinitions><RowDefinition /><RowDefinition /></Grid.RowDefinitions><Grid.ColumnDefinitions><ColumnDefinition Width="Auto" /><ColumnDefinition /></Grid.ColumnDefinitions><TextBlock Text="Name:" /><TextBox Grid.Column="1"Margin="1" Text="{Binding Name,ValidatesOnExceptions=True,UpdateSourceTrigger=PropertyChanged}" /><TextBlock Grid.Row="1" Text="Age:" /><TextBox Grid.Row="1"Grid.Column="1"Margin="1"Text="{Binding Age,ValidatesOnExceptions=True,UpdateSourceTrigger=PropertyChanged}" /></Grid>

    使用特性的方式,能夠很自由的使用自定義的規(guī)則,而且在.Net4.5中新增了很多特性,可以很方便的對(duì)數(shù)據(jù)進(jìn)行校驗(yàn)。

    例如:EmailAddress, Phone, and Url等。

    ?

    三、自定義錯(cuò)誤顯示模板

    在上面的例子中,我們可以看到當(dāng)出現(xiàn)驗(yàn)證不正確時(shí),綁定控件會(huì)被一圈紅色錯(cuò)誤線包裹住。

    這種方式一般不能夠正確的展示出,錯(cuò)誤的原因等信息,所以有可能需要自己的錯(cuò)誤顯示方式。

    前面,我們已經(jīng)講過(guò)了。當(dāng)在檢測(cè)過(guò)程中,出現(xiàn)錯(cuò)誤時(shí),WPF會(huì)把錯(cuò)誤信息封裝為一個(gè)ValidationError對(duì)象,

    并添加到Validation.Errors中,所以我們可以取出錯(cuò)誤詳細(xì)信息,并顯示出來(lái)。

    1、為控件創(chuàng)建ErrorTemplate

    下面就是一個(gè)簡(jiǎn)單的例子,每次都把錯(cuò)誤信息以紅色展示在空間上面。這里的AdornedElementPlaceholder相當(dāng)于

    控件的占位符,表示控件的真實(shí)位置。這個(gè)例子是在書(shū)上直接拿過(guò)來(lái)的,只能做基本展示用。

    <ControlTemplate x:Key="ErrorTemplate"><Border BorderBrush="Red" BorderThickness="2"><Grid><AdornedElementPlaceholder x:Name="_el" /><TextBlock Margin="0,0,6,0"HorizontalAlignment="Right"VerticalAlignment="Center"Foreground="Red"Text="{Binding [0].ErrorContent}" /></Grid></Border></ControlTemplate> <TextBox x:Name="AgeTextBox"Grid.Row="1"Grid.Column="1"Margin="1" Validation.ErrorTemplate="{StaticResource ErrorTemplate}" >

    使用方式非常簡(jiǎn)單,將上面的模板作為邏輯資源加入項(xiàng)目中,然后像上面一樣引用即可。

    效果圖:

    對(duì)知識(shí)梳理總結(jié),希望對(duì)大家有幫助!

    posted on 2018-09-21 10:24 NET未來(lái)之路 閱讀(...) 評(píng)論(...) 編輯 收藏

    轉(zhuǎn)載于:https://www.cnblogs.com/lonelyxmas/p/9685193.html

    總結(jié)

    以上是生活随笔為你收集整理的[WPF 基础知识系列] —— 绑定中的数据校验Vaildation的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。