上一篇,着重介紹了Silverlight客戶端同步數據驗證機制,演示了IDataErrorInfo接口的實現方法。在一些實際的Silverlight企業級項目中,我們經常會遇到通過服務對數據進行驗證,另外應用在驗證的同時,不會影響其他功能的運行,也就是我們常提及的異步操作,這樣的需求IDataErrorInfo接口和前期我們討論過的DataAnotation驗證機制都無法實現。另外在一些項目中,開發人員會綁定多個錯誤到一個數據成員,而IDataErrorInfo和DataAnotation也無法實現。Silverlight 4中,微軟引入一個新的接口INotifyDataErrorInfo,該接口的實現,可以輕鬆的解決以上兩個問題。
INotifyDataErrorInfo接口和IDataErrorInfo相同,命名空間都是System.ComponentModel。
該接口是爲數據成員提供自定義的同步或者異步驗證支持。最常用的是對異步驗證的支持,另外,可支持單屬性中綁定多個錯誤信息。
INotifyDataErrorInfo接口具有一個屬性,一個方法,一個事件,分別是:
HasErrors, 這個屬性判斷當前對象中是否有錯誤,如果返回True則說明對象出現驗證錯誤,反之則False。
方法:
GetErrors, 這個方法負責返回特定驗證成員中所有的驗證錯誤信息,如果PropertyName參數爲null或者string.empty,該方法將返回一個錯誤到全局對象中。
事件:
ErrorsChanged,該事件與上篇我們提及的PropertyChanged事件相似。當添加,刪除,修改驗證錯誤時,將激活該事件通知綁定系統,更新UI。
實現INotifyDataErrorInfo接口,支持服務器端異步驗證,所以,本實例將創建一個Web服務,演示該接口驗證效果。
本篇實例,我們仍舊使用SilverlightValidationDemo項目,爲了不和過去的驗證方法衝突,這裏我們創建一個新的數據成員類Staff,該類實現INotifyDataErrorInfo接口和INotifyPropertyChanged接口. 其默認代碼如下,後面我們將逐漸完善這些代碼,
public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;
public System.Collections.IEnumerable GetErrors(string propertyName)
{
throw new NotImplementedException();
}
public bool HasErrors
{
get { throw new NotImplementedException(); }
}
#endregion
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
#endregion
另外定義一個新的數據成員,UserName
private string _username;
public string UserName
{
get { return _username; }
set
{
_username = value;
}
}
#endregion
完成以上的客戶端準備步驟,我們首先到Web服務器端創建一個Silverlight enabled WCF Service, ValidationService。 這裏我不再演示具體的創建步驟,如果不會創建的,請參考這裏:圖文詳解Silverlight訪問MSSQL數據庫
在服務端,我們創建簡單的驗證代碼,如下
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class ValidationService
{
[OperationContract]
public bool ValidationUserName(string username)
{
if (username == "jv9")
return true;
else
return false;
}
}
創建完畢後,編譯SilverlightValidationDemo.Web項目,然後回到Silverlight客戶端,添加一個新的服務引用,
搜索到剛創建的ValidationService服務,添加到客戶端,Visual Studio 2010會自動創建客戶端配置文件ServiceReferences.ClientConfig,
到這裏一個WCF服務已經創建成功,下面,修改Staff類,
之前,我們已經創建了新的數據成員UserName,另外執行INotifyDataErrorInfo接口,自動生成ErrorsChanged事件,GetErrors方法和HasErrors屬性。
首先,需要對GetErrors方法進行重構,創建全局變量_validationErrors,承載驗證錯誤信息集合.
public System.Collections.IEnumerable GetErrors(string propertyName)
{
if (!string.IsNullOrEmpty(propertyName))
{
if (_validationErrors.ContainsKey(propertyName))
return _validationErrors[propertyName];
else
return null;
}
else
return null;
}
然後,對HasErrors屬性進行重構,,判斷是否有驗證錯誤,
{
get
{
foreach (string key in _validationErrors.Keys)
{
if (_validationErrors[key].Count > 0)
return true;
}
return false;
}
}
創建構造函數,和初始化錯誤集合,
{
_validationErrors = new Dictionary<string, ObservableCollection<string>>();
GenerateErrorsCollection("UserName");
}
#endregion
#region private methods
private void GenerateErrorsCollection(string propertyName)
{
if (!_validationErrors.ContainsKey(propertyName))
{
_validationErrors.Add(propertyName, new ObservableCollection<string>());
}
}
添加調用服務客戶端代碼,
{
var client = new ValidationService.ValidationServiceClient();
client.ValidationUserNameCompleted += (o, e) =>
{
_validationErrors["UserName"].Clear();
if (e.Result)
{
_username = username;
NotifyPropertyChanged("UserName");
}
else
{
_validationErrors["UserName"].Add("服務器端返回錯誤,用戶名必須是jv9");
}
if (ErrorsChanged != null)
{
ErrorsChanged(this, new DataErrorsChangedEventArgs("UserName"));
}
};
client.ValidationUserNameAsync(username);
}
在數據成員中,添加驗證方法調用,
private string _username;
public string UserName
{
get { return _username; }
set
{
_username = value;
ValidateUserNameandPasswordAsync(value);
}
}
#endregion
其運行效果:
在每次修改用戶框內容後,應用會自動向WCF服務請求驗證,如果驗證失敗,則彈出驗證錯誤信息,反之,則繼續。
INotifyPropertyChanged接口,相比前面介紹的幾個驗證機制,其複雜程度較高,需要開發人員設計部分代碼,但是其異步服務器端數據驗證功能和單一屬性添加多個錯誤信息功能,是Silverlight企業級項目中常用到的功能。在隨後的項目中,我們會使用更多實例演示其強大功能。
今天就到這裏了。
源代碼下載 |