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

 

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