俊鸟的数据输入校验专题(三) WPF 的五种输入校验概述
雖然wpf內部有驗證方案,但在實際應用中,會出現一些問題.這里發出來與大家共同討論.作為使用者,你喜歡哪一種呢?這里不解釋數據綁定的知識,因為不夠專業,怕會誤導,索性不寫.但我相信大家會遇到這個問題.本文是通過多個示例比較得出的想法.
1.通過繼承ValidationRule抽象類,定義驗證規則重寫Validate方法
這里是sdk的示例代碼
public?class?AgeRangeRule?:?ValidationRule
????{
????????private?int?_min;
????????private?int?_max;
????????public?AgeRangeRule()
????????{
????????}
????????public?int?Min
????????{
????????????get?{?return?_min;?}
????????????set?{?_min?=?value;?}
????????}
????????public?int?Max
????????{
????????????get?{?return?_max;?}
????????????set?{?_max?=?value;?}
????????}
????????public?override?ValidationResult?Validate(object?value,?CultureInfo?cultureInfo)
????????{
????????????int?age?=?0;
????????????try
????????????{
????????????????if?(((string)value).Length?>?0)
????????????????????age?=?Int32.Parse((String)value);
????????????}
????????????catch?(Exception?e)
????????????{
????????????????return?new?ValidationResult(false,?"Illegal?characters?or?"?+?e.Message);
????????????}
????????????if?((age?<?Min)?||?(age?>?Max))
????????????{
????????????????return?new?ValidationResult(false,
??????????????????"Please?enter?an?age?in?the?range:?"?+?Min?+?"?-?"?+?Max?+?".");
????????????}
????????????else
????????????{
????????????????return?new?ValidationResult(true,?null);
????????????}
????????}
????}
然后是xaml的使用代碼
?????????????Validation.ErrorTemplate="{StaticResource?validationTemplate}"
?????????????Style="{StaticResource?textBoxInError}"
?????????????Grid.Row="1"?Grid.Column="1"?Margin="2">
??????<TextBox.Text>
????????<Binding?Path="Age"?Source="{StaticResource?ods}"
?????????????????UpdateSourceTrigger="PropertyChanged"?>
??????????<Binding.ValidationRules>
????????????<c:AgeRangeRule?Min="21"?Max="130"/>
??????????</Binding.ValidationRules>
????????</Binding>
??????</TextBox.Text>
????</TextBox>
就是通過ValidationRules集合掛驗證規則.如果邏輯不復雜的話,勉強可以接受,這里我個人認為可以作為界面的驗證.但如果業務邏輯一旦發生變化,則意味著xaml文件一直需要修改,這并不是一種好的做法,并不推薦.(而且內置的驗證規則太少了,有的話還勉強用用,都需要自己重寫)
2.通過正則表達式附加屬性簡化寫法,大家應該知道,驗證部分,正則表達式占了很大部分.
定義一個正則表達式類,然后通過附加屬性進行驗證.具體的方案,請參考這里
http://www.codeproject.com/WPF/RegexValidationInWPF.asp
然后前端xaml的使用方法
??????Text="{Binding?Path=EmailAddress,?UpdateSourceTrigger=PropertyChanged}"?
??????jas:RegexValidator.RegexText="^[a-zA-Z0-9._%-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$"?
??????jas:RegexValidator.ErrorMessage="Invalid?e-mail?address."?
??????/>
代碼是簡化了,但有個缺點,只能定義一個驗證規則,也存在著我上面提到的問題,把正則寫在ui上面,并不是一個好的做法,應該對其進行封裝(看著這么多符號就心慌,高手可以這么做),也并不推薦的做法.
3.與業務邏輯驗證綁定在一起
這種做法與上面的都不同,因為業務邏輯的判斷與常規的判斷比如(比如是否必填,字符匹配等),而且前端只需要綁定字段就可以了,先看前端的做法
請注意,這里并沒有寫什么驗證規則或正則表達式哦,真正的驗證在這里,驗證的對象必須實現IDataErrorInfo接口,通過索引器,可以判斷對象的每個字段.
上面緊緊是FirstName,這里是通過整個對象的業務邏輯判斷的,否則你需要在ui上面都定義一個驗證規則,非常麻煩(比如有2個字段,你必須對兩個字段都定義驗證規則(即第一種方法)).這種做法是比較好的,把邏輯與ui分開了,值得推薦.sdk示例代碼
????{
????????private?int?age;
????????public?int?Age
????????{
????????????get?{?return?age;?}
????????????set?{?age?=?value;?}
????????}
????????public?string?Error
????????{
????????????get
????????????{
????????????????return?null;
????????????}
????????}
????????public?string?this[string?name]
????????{
????????????get
????????????{
????????????????string?result?=?null;
????????????????if?(name?==?"Age")
????????????????{
????????????????????if?(this.age?<?0?||?this.age?>?150)
????????????????????{
????????????????????????result?=?"Age?must?not?be?less?than?0?or?greater?than?150.";
????????????????????}
????????????????}
????????????????return?result;
????????????}
????????}
????}
但還有些問題,如果我在第3點的基礎上,我還要加一個普通的判斷,比如必填驗證,長度驗證,還是逃不了驗證規則這一步.
這里我們要做出選擇
把規則定義在ui上(變動太大,不適合,無奈之舉)
寫在業務邏輯里面(這樣下來,邏輯未免太復雜)
4.以元數據的形式(在屬性上掛標簽)
在codeproject上,我找到一個比較完美的解決方案,作者自己重新定義了一套標簽,使用也比較簡單(代碼是vb的,編譯后再反編譯用c#看:)),這種做法已經接近了要求.大家去看看這篇文章,非常的不錯.其在還為前端提供了一個ui顯示錯誤的一個下拉列表.不過通過這個例子,我又想到一個更好的東西.
5.使用EnterPrise Library Validation Application Block(再好不過)
由于wpf的屬性使用了大量的依賴屬性,我原以為這個好東西在wpf算是廢了,通過第3點和第4點,我們終于可以引進這個企業級模塊了。如下做法
????public?abstract?class?BaseValidationEntity<T>?:?IDataErrorInfo,?INotifyPropertyChanged
????{
????????IDataErrorInfo?Members#region?IDataErrorInfo?Members
????????public?string?Error
????????{
????????????get?{?return?null;?}
????????}
????????private?T?_entity;
????????public?bool?Valid()
????????{
????????????Validator<T>?validator?=?ValidationFactory.CreateValidator<T>();
????????????ValidationResults?results?=?validator.Validate(this);
????????????return?results.Count?==?0;
????????}
????????public?string?this[string?name]
????????{
????????????get
????????????{
????????????????
????????????????string?result?=?null;
????????????????
????????????????Validator<T>?validator?=?ValidationFactory.CreateValidator<T>();
????????????????ValidationResults?results?=?validator.Validate(this);
????????????????if?(results.Count?>?0)
????????????????{
????????????????????return?results.First().Message;
????????????????????//foreach?(var?item?in?results)
????????????????????//{
????????????????????//????result?+=?item.Message;
????????????????????//}
????????????????}
????????????????return?result;
????????????}
????????}
????????#endregion
????????protected?void?OnPropertyChanged(string?name)
????????{
????????????PropertyChangedEventHandler?handler?=?PropertyChanged;
????????????if?(handler?!=?null)
????????????{
????????????????handler(this,?new?PropertyChangedEventArgs(name));
????????????}
????????}
????????INotifyPropertyChanged?Members#region?INotifyPropertyChanged?Members
????????public?event?PropertyChangedEventHandler?PropertyChanged;
????????#endregion
????}
然后繼承之,隨便定一個對象來demo
????{
????????private?string?firstName;
????????[StringLengthValidator(4,?10,MessageTemplate="aaa")]
????????[RegexValidator(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*",?MessageTemplate?=?"Invalid?e-mail?address")]
????????public?string?FirstName
????????{
????????????get?{?return?firstName;?}
????????????set?{?firstName?=?value;
????????????OnPropertyChanged("FirstName");
????????????}
????????}
????}
我們看到熟悉的標簽了,目前我認為這種方案最好,當然我們也可以通過配置xml來實現,這樣真正做到了界面與邏輯分離。
上面一層的做到了邏輯上的驗證,至于界面如何顯示錯誤,我們可以通過Error屬性來定制一個控件,這個暫不討論了
在學習wpf的朋友,歡迎一起討論。
?參考文章
http://blogs.msdn.com/wpfsdk/archive/2007/10/02/data-validation-in-3-5.aspx
轉載于:https://www.cnblogs.com/junbird-nest/archive/2012/06/18/2553739.html
總結
以上是生活随笔為你收集整理的俊鸟的数据输入校验专题(三) WPF 的五种输入校验概述的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: (转)标准I/O缓冲:全缓冲、行缓冲、无
- 下一篇: Eclipse保存验证JS缓慢