Silverlight輸入數據驗證系列三

Silverlight實例教程 - Validation客戶端同步數據驗證

時間:2010-09-13 19:24來源:SilverlightChina.Net 作者:Jv9 點擊: 281次
前文介紹過Silverlight Validation中兩個數據驗證機制, ValidatesOnExceptions異常捕獲驗 證 機制和 DataAnnotation驗證機制,這兩種驗證機制,是在Silverlight 3 Validation Framework推出的,其運行方式類似,都是當異常拋出後,應用對異常信息進行捕獲,並顯示在客
  

 

 

前文介紹過Silverlight Validation中兩個數據驗證機制,ValidatesOnExceptions異常捕獲驗機制DataAnnotation驗證機制,這兩種驗證機制,是在Silverlight 3 Validation Framework推出的,其運行方式類似,都是當異常拋出後,應用對異常信息進行捕獲,並顯示在客戶端。在Silverlight 4中,Silverlight Validation有相對的改進,本篇將介紹Silverlight 4中新加入的驗證機制功能,IDataErrorInfo客戶端同步驗證機制。

 

Silverlight 4 IDataErrorInfo接口概述

相信熟悉WPF的開發人員都知道,WPF也具有IdataErrorInfo接口,其接口可以無需拋出任何異常,即可對數據進行驗證。而Silverlight的IDataErrorInfo接口就是從WPF中轉化來的。與前面兩種驗證機制相比,Silverlight 4 IDataErrorInfo提供的同步驗證方式,不再需要基於異常拋出的基礎上來激活驗證,簡單的理解,就是當值驗證失敗的時候,不會拋出任何異常信息。這種驗證機制,相對前兩種驗證機制來說更加靈活。

 

Silverlight 4 IDataErrorInfo接口類成員

IDataErrorInfo接口,位於System.ComponentModel命名空間。該接口主要被應用在需要對其進行驗證的數據成員類。

 

代碼
 1         #region IDataErrorInfo Members
 2 
 3         public string Error
 4         {
 5             get { throw new NotImplementedException(); }
 6         }
 7 
 8         public string this[string columnName]
 9         {
10             get { throw new NotImplementedException(); }
11         }
12 
13         #endregion

 

 

IDataErrorInfo接口具有兩個屬性

 

1. Error: 該屬性爲驗證設置屬性錯誤提示信息;

2. Item: 該屬性爲錯誤信息集合,其中索引值爲屬性名,將其對應的錯誤信息,設置到指定的被驗證控件中;

 

從MSDN對IdataErrorInfo接口的解釋中可以看到,IDataErrorInfo接口,沒有任何事件方法被預先定義。也就是說,IDataErrorInfo接口本身不具備自動激活驗證功能。簡單的可以理解成爲,當驗證錯誤產生時,該錯誤信息不會自動捕獲,然後顯示到用戶客戶端上。解決該問題,需要引入另外一個接口INotifyPropertyChanged。對Silverlight早期版本熟悉的開發人員,應該對INotifyPropertyChanged接口並不陌生,該接口主要功能是當數據成員改變時發出通知到客戶端,是Silverlight中最常用的一個接口,這裏對該接口不再贅述。

 

public class Customer  : INotifyPropertyChanged

 

 

    public event PropertyChangedEventHandler PropertyChanged;

    
private void NotifyPropertyChanged(String info)
    {
        
if (PropertyChanged != null)
        {
            PropertyChanged(
thisnew PropertyChangedEventArgs(info));
        }
    }

 

 

    public string CustomerName
    {
        
get
        {
            
return this.customerNameValue;
        }

        
set
        {
            
if (value != this.customerNameValue)
            {
                
this.customerNameValue = value;
                NotifyPropertyChanged(
"CustomerName");
            }
        }
    }

 

 

在使用了INotifyPropertyChanged接口後,每當數據成員驗證錯誤產生時,都會執行IDataErrorInfo接口,檢測Error和Item屬性。但是僅僅使用INotifyPropertyChanged接口,還無法正常將錯誤信息顯示在客戶端,同時也需要在客戶端添加新的綁定驗證屬性ValidatesOnDataErrors, 該屬性在默認綁定情況下是False,如果使用IDataErrorInfo接口,則需要使用True,這時,客戶端纔會顯示IDataErrorInfo接口被執行後產生的驗證錯誤信息。

 

<TextBox Text="{Binding CustomerName,Mode=TwoWay,ValidatesOnDataErrors=true}" />

 

講到這裏,我們可以結合前兩篇講解的綁定驗證屬性,來理解IDataErrorInfo接口。

使用IDataErrorInfo接口,必須結合INotifyPropertyChanged接口使用,否則UI無法獲取到相對應屬性的錯誤關聯信息。

而使用IDataErrorInfo接口綁定驗證屬性時,在客戶端控件內容綁定中使用ValidatesOnDataErrors = True,

另外,如果需要使用BindingValidationError事件,在客戶端控件內容中,需要再綁定NotifyOnValidationError = True,

如果需要對異常進行捕獲相應,同時,也需要綁定ValidatesOnExceptions = True。

 

IDataErrorInfo接口使用實例演示

 

本實例仍舊使用上一篇的實例代碼,在其基礎上添加對IDataErrorInfo接口的調用,

首先在User數據成員類中,執行IDataErrorInfo和INotifyPropertyChanged接口

 

       #region IDataErrorInfo Members

        
private string _dataError = string.Empty;
        
public string Error
        {
            
get { return _dataError; }
        }

        
private Dictionary<stringstring> _dataErrors = new Dictionary<stringstring>();
        
public string this[string columnName]
        {
            
get 
            {
                
if (_dataErrors.ContainsKey(columnName))
                    
return _dataErrors[columnName];
                
else
                    
return null;
            }
        }

        
#endregion

        
#region INotifyPropertyChanged Members

        
public event PropertyChangedEventHandler PropertyChanged;
        
protected void NotifyPropertyChanged(string propertyName)
        {
            
if (PropertyChanged != null)
                PropertyChanged(
thisnew PropertyChangedEventArgs(propertyName));
        }

        
#endregion

 

 

其中IDataErrorInfo中定義的Dictionary是驗證錯誤集合。而INotifyPropertyChanged是最簡單的當數據成員改變時返回通知到客戶端,其中沒有過多的邏輯代碼。

 

我們使用最簡單的數據成員生成一個驗證錯誤,IDataErrorInfo捕獲顯示作爲演示,

 

 在User類中,添加一個Address地址數據成員,

 

        private string _address;
        
public string address
        {
            
get
            {
                
return _address;
            }
            
set
            {
                _address 
= value;
            }
        }

 

 

然後在set中添加簡單的邏輯代碼,

 

        private string _address;
        
public string address
        {
            
get
            {
                
return _address;
            }
            
set
            {
                
if (string.IsNullOrEmpty(value))
                    _dataErrors[
"address"= "地址必須填寫";
                
else if (value.Trim().Length < 6)
                    _dataErrors[
"address"= "地址至少6個字";
                
else
                    
if (_dataErrors.ContainsKey("address"))
                        _dataErrors.Remove(
"address");

                _address 
= value;
                NotifyPropertyChanged(
"address");
            }
        }

 

 

修改前臺,添加新的輸入框,另外綁定輸入框內容到address,

 

 

<StackPanel Orientation="Horizontal" Margin="5">
                
<TextBlock Text="地   址: " VerticalAlignment="Center"/>
                
<TextBox x:Name="txtAddress" Width="200" DataContext="{Binding Source={StaticResource UserDataContext}}" Text="{Binding Path=address, Mode=TwoWay, ValidatesOnDataErrors=True}" />
</StackPanel>

 

 

其運行結果爲:

 

 

下面,我們做一個較爲複雜一些的數據驗證,

學生成績對應表

A   -  90-100分

B   -  80-89分

C   -  70-79分

D   -  60-69分

F   -  0-59分

 

在這個實例中,我們對多個數據成員進行客戶端數據驗證。

添加兩個新數據成員,gradelevel和graderange,其中使用獨立的驗證函數ValidateGradeLevelandRange進行數據驗證,

 

        private string _gradelevel;
        
public string gradelevel
        {
            
get { return _gradelevel; }
            
set
            {
                
if (ValidateGradeLevelandRange(value,graderange))
                {
                    _gradelevel 
= value;
                    NotifyPropertyChanged(
"gradelevel");
                }
            }
        }

        
private decimal _graderange;
        
public decimal graderange
        {
            
get { return _graderange; }
            
set
            {
                
if (ValidateGradeLevelandRange(gradelevel, value))
                {
                    _graderange 
= value;
                    NotifyPropertyChanged(
"graderange");
                }
            }
        }

 

 

 

#region Customize Validation
        
private bool ValidateGradeLevelandRange(string level, decimal range)
        {
            
bool isValid = false;

            
if (level == null)
            {
                _dataErrors[
"gradelevel"= "成績等級必須是A,B,C,D,F";
                
return false;
            }
            
else
            {
                
switch (level.ToUpper())
                {
                    
case "A":
                        isValid 
= (range >= 90 && range <= 100);
                        
break;
                    
case "B":
                        isValid 
= (range >= 80 && range <= 89);
                        
break;
                    
case "C":
                        isValid 
= (range >= 70 && range <= 79);
                        
break;
                    
case "D":
                        isValid 
= (range >= 60 && range <= 69);
                        
break;
                    
case "F":
                        isValid 
= (range >= 0 && range <= 59);
                        
break;
                    
default:
                        _dataErrors[
"gradelevel"= "成績等級必須是A,B,C,D,F";
                        
return false;
                }
            }

            
if (isValid)
            {
                
if (_dataErrors.ContainsKey("gradelevel"))
                    _dataErrors.Remove(
"gradelevel");
                
if (_dataErrors.ContainsKey("graderange"))
                    _dataErrors.Remove(
"graderange");
            }
            
else
            {
                _dataErrors[
"gradelevel"= "成績等級和成績範圍不符合";
                _dataErrors[
"graderange"= "成績範圍和成績等級不符合";
            }

            
return isValid;
        }
        
#endregion

 

 

在前臺添加兩個成績輸入框,

 

 

            <StackPanel Orientation="Horizontal" Margin="5">
                
<TextBlock Text="成績等級: " VerticalAlignment="Center"/>
                
<TextBox x:Name="txtGradeLevel" Width="200" DataContext="{Binding Source={StaticResource UserDataContext}}" Text="{Binding Path=gradelevel, Mode=TwoWay, ValidatesOnDataErrors=True, NotifyOnValidationError=False, ValidatesOnExceptions=True}" />
            
</StackPanel>
            
<StackPanel Orientation="Horizontal" Margin="5">
                
<TextBlock Text="成績範圍: " VerticalAlignment="Center"/>
                
<TextBox x:Name="txtGradeRange" Width="200" DataContext="{Binding Source={StaticResource UserDataContext}}" Text="{Binding Path=graderange, Mode=TwoWay, ValidatesOnDataErrors=True, NotifyOnValidationError=False, ValidatesOnExceptions=True}" />
            
</StackPanel>

 

 

其最終運行結果如下:

 

 

今天內容講到這裏了。

 

源代碼下載

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章