1、介紹
INotifyPropertyChanged是一個接口,該接口包含一個事件, 針對屬性發生變更時, 執行該事件發生。
//
// 摘要:
// 通知客戶端屬性值已更改。
public interface INotifyPropertyChanged
{
//
// 摘要:
// 在屬性值更改時發生。
event PropertyChangedEventHandler PropertyChanged;
}
作用:監聽屬性值的變化。
有時候,我們需要監聽屬性值的變化,當屬性值發生改變時,需要被通知,沒有改變時不需要通知,這個時候可以用INotifyPropertyChanged來做,也可以自定義委託事件,目的是當屬性值發生變化時,才觸發事件。
2、使用
(1)定義一個ViewModelBase 繼承INotifyPropertyChanged 接口, 添加一個虛函數用於繼承子類的屬性進行更改通知。
//ViewModelBase類
public class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
if (this.PropertyChanged != null)//有改變
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
(2)定義一個MainViewModel類 繼承ViewModelBase類,MainViewModel中兩個屬性, Code,Name 進行了Set更改時候的調用通知。
public class MainViewModel:ViewModelBase
{
private string _name;
private string _code;
public string Name
{
get{return _name;}
set
{
_name = value;
base.OnPropertyChanged("Name");
}
}
public string Code
{
get{return _code;}
set
{
_code = value;
base.OnPropertyChanged("Code");
}
}
}
正如上面的代碼, 應該注意到了, 每個屬性調用OnPropertyChanged的時候, 都需要傳一個自己的屬性名, 這樣是不是很多餘?對, 很多餘。
3、改進
CallerMemberName類
該類繼承與 Attribute, 不難看出, 該類屬於定義在方法和屬性上的一種特效類, 實現該特性允許獲取方法調用方的方法或屬性名稱。
//
// 摘要:
// 允許獲取方法調用方的方法或屬性名稱。
[AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
public sealed class CallerMemberNameAttribute : Attribute
{
//
// 摘要:
// 初始化 System.Runtime.CompilerServices.CallerMemberNameAttribute 類的新實例。
public CallerMemberNameAttribute();
}
(1)改造ViewModelBase類
//ViewModelBase類
public class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName]string propertyName = null)
{
if (this.PropertyChanged != null)//有改變
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
(2)MainViewModel類引用
public class MainViewModel:ViewModelBase
{
private string _name;
private string _code;
public string Name
{
get{return _name;}
set
{
_name = value;
base.OnPropertyChanged();
}
}
public string Code
{
get{return _code;}
set
{
_code = value;
base.OnPropertyChanged();
}
}
}
4、最佳實現
參考:https://www.cnblogs.com/bcmeng/p/3966931.html
public class ModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected bool SetProperty<T>(ref T storage, T value, [CallerMemberName] String propertyName = null)
{
if (object.Equals(storage, value)) return false;
storage = value;
this.OnPropertyChanged(propertyName);
return true;
}
protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
var eventHandler = this.PropertyChanged;
if (eventHandler != null)
eventHandler(this, new PropertyChangedEventArgs(propertyName));
}
}
相應的調用方式進一步簡化:
public class Model:ModelBase
{
private string name;
public string Name
{
get { return name; }
set
{ this.SetProperty(ref this.name, value); }
}
}