轉(zhuǎn)帖|其它|編輯:郝浩|2011-03-08 13:38:21.000|閱讀 669 次
概述:大家都知道, 在使用 Silverlight 數(shù)據(jù)綁定的時(shí)候, 為了使源對象的更改能夠傳播到目標(biāo),源必須實(shí)現(xiàn) INotifyPropertyChanged 接口。INotifyPropertyChanged 具有 PropertyChanged 事件,該事件通知綁定引擎源已更改,以便綁定引擎可以更新目標(biāo)值。本文的內(nèi)容雖然是針對 Silverlight 數(shù)據(jù)綁定而寫的, 對于 WPF 數(shù)據(jù)綁定也很適用。
# 界面/圖表報(bào)表/文檔/IDE等千款熱門軟控件火熱銷售中 >>
大家都知道, 在使用 Silverlight 數(shù)據(jù)綁定的時(shí)候, 為了使源對象的更改能夠傳播到目標(biāo),源必須實(shí)現(xiàn) INotifyPropertyChanged 接口。INotifyPropertyChanged 具有 PropertyChanged 事件,該事件通知綁定引擎源已更改,以便綁定引擎可以更新目標(biāo)值。
下面是一個(gè)典型的例子:
public class UserModel : INotifyPropertyChanged {
private string _firstName;
private string _lastName;
public string FirstName {
get {
return this._firstName;
}
set {
this._firstName = value;
this.NotifyPropertyChanged("FirstName");
}
}
public string LastName {
get {
return this._lastName;
}
set {
this._lastName = value;
this.NotifyPropertyChanged("LastName");
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void NotifyPropertyChanged(string propertyName) {
if (this.PropertyChanged != null) {
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
在這個(gè)例子中,設(shè)置 FirstName 、LastName 時(shí),需要手工激發(fā) PropertyChanged 事件, 通知綁定引擎,因此, 如果數(shù)據(jù)源中屬性比較多的時(shí)候, 是比較煩人的, 每個(gè)屬性的 Setter 都需要激發(fā)一下 PropertyChanged 事件, 而且不能使用 C# 自帶的自動(dòng)屬性特性。 當(dāng)然, 可以自己設(shè)置一個(gè)代碼段 snippet 來解決, 但是,重復(fù)的激發(fā) PropertyChanged 事件的代碼依然存在, 這不是我們的目標(biāo)。
前段時(shí)間看到有人在抱怨 Silverlight 的數(shù)據(jù)綁定,說必須要實(shí)現(xiàn) INotifyPropertyChanged 接口, 而且還要手工調(diào)用 NotifyPropertyChanged 事件等等, 我想說的是, 借助 Castal DynamicProxy 提供的攔截技術(shù),可以把手工調(diào)用 NotifyPropertyChanged 事件的代碼省掉。
INotifyPropertyChanged 接口是 Silverlight 數(shù)據(jù)綁定必須的, 這一點(diǎn)我們無法改變。因此需要先創(chuàng)建一個(gè) BaseModel , 并讓其實(shí)現(xiàn) INotifyPropertyChanged 接口,代碼如下:
public class BaseModel : INotifyPropertyChanged {
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged(string propertyName) {
if (this.PropertyChanged != null) {
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
接下來為 BaseModel 寫一個(gè)攔截器, 讓所有繼承自 BaseModel 的類在設(shè)置屬性之后自動(dòng)激發(fā) NotifyPropertyChanged 事件, 攔截器代碼如下:
public class NotifyPropertyChangedInterceptor : StandardInterceptor {
protected override void PostProceed(IInvocation invocation) {
base.PostProceed(invocation);
var methodName = invocation.Method.Name;
// 這里可能不是很完善, 屬性的 Setter 一般都是以 set_ 開頭的,
// 應(yīng)該有更好的判斷方法。
if (methodName.StartsWith("set_")) {
var propertyName = methodName.Substring(4);
var target = invocation.Proxy as BaseModel;
if (target != null) {
target.NotifyPropertyChanged(propertyName);
}
}
}
}
攔截器的代碼很簡單, 而且是可以擴(kuò)展的, 相信都能看懂, 我們還需要一個(gè) ModelHelper , 來方便的創(chuàng)建 Proxy , ModelHelper 的代碼如下:
public static class ModelHelper {
private static readonly ProxyGenerator ProxyGenerator = new ProxyGenerator();
private static readonly NotifyPropertyChangedInterceptor Interceptor = new NotifyPropertyChangedInterceptor();
public static T CreateProxy≶T>(T obj) where T : class, INotifyPropertyChanged {
return ProxyGenerator.CreateClassProxyWithTarget(obj, Interceptor);
}
}
有了 ModelHelper , 可以說是萬事俱備了, 我們來重寫上邊的 UserModel , UserModel 最終的代碼如下:
public class UserModel : BaseModel {
public virtual string FirstName {
get;
set;
}
public virtual string LastName {
get;
set;
}
}
最后,使用 UserModel 的代碼是這樣的:
public partial class MainPage : UserControl {
public MainPage() {
InitializeComponent();
// 不能直接使用 UserModel, 要通過 ModelHelper 創(chuàng)建一個(gè) Proxy 才行。
var dataContext = ModelHelper.CreateProxy(new UserModel());
dataContext.FirstName = "Zhang";
dataContext.LastName = "ZhiMin";
this.DataContext = dataContext;
}
}
本文的內(nèi)容雖然是針對 Silverlight 數(shù)據(jù)綁定而寫的, 對于 WPF 數(shù)據(jù)綁定也很適用。
本站文章除注明轉(zhuǎn)載外,均為本站原創(chuàng)或翻譯。歡迎任何形式的轉(zhuǎn)載,但請務(wù)必注明出處、不得修改原文相關(guān)鏈接,如果存在內(nèi)容上的異議請郵件反饋至chenjj@ke049m.cn
文章轉(zhuǎn)載自:網(wǎng)絡(luò)轉(zhuǎn)載