C#--INotifyPropertyChanged

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); }
        }
    }

 

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