Implementing INotifyPropertyChanged - does a better way exist?

前端 未结 30 2673
感情败类
感情败类 2020-11-21 05:23

Microsoft should have implemented something snappy for INotifyPropertyChanged, like in the automatic properties, just specify {get; set; notify;} I

30条回答
  •  时光说笑
    2020-11-21 05:33

    Based on the answer by Thomas which was adapted from an answer by Marc I've turned the reflecting property changed code into a base class:

    public abstract class PropertyChangedBase : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
    
        protected void OnPropertyChanged(string propertyName)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null) 
                handler(this, new PropertyChangedEventArgs(propertyName));
        }
    
        protected void OnPropertyChanged(Expression> selectorExpression)
        {
            if (selectorExpression == null)
                throw new ArgumentNullException("selectorExpression");
            var me = selectorExpression.Body as MemberExpression;
    
            // Nullable properties can be nested inside of a convert function
            if (me == null)
            {
                var ue = selectorExpression.Body as UnaryExpression;
                if (ue != null)
                    me = ue.Operand as MemberExpression;
            }
    
            if (me == null)
                throw new ArgumentException("The body must be a member expression");
    
            OnPropertyChanged(me.Member.Name);
        }
    
        protected void SetField(ref T field, T value, Expression> selectorExpression, params Expression>[] additonal)
        {
            if (EqualityComparer.Default.Equals(field, value)) return;
            field = value;
            OnPropertyChanged(selectorExpression);
            foreach (var item in additonal)
                OnPropertyChanged(item);
        }
    }
    

    Usage is the same as Thomas' answer except that you can pass additional properties to notify for. This was necessary to handle calculated columns which need to be refreshed in a grid.

    private int _quantity;
    private int _price;
    
    public int Quantity 
    { 
        get { return _quantity; } 
        set { SetField(ref _quantity, value, () => Quantity, () => Total); } 
    }
    public int Price 
    { 
        get { return _price; } 
        set { SetField(ref _price, value, () => Price, () => Total); } 
    }
    public int Total { get { return _price * _quantity; } }
    

    I have this driving a collection of items stored in a BindingList exposed via a DataGridView. It has eliminated the need for me to do manual Refresh() calls to the grid.

提交回复
热议问题