【问题标题】:INotifyPropertyChanged best practicesINotifyPropertyChanged 最佳实践
【发布时间】:2011-11-08 01:53:03
【问题描述】:

当我有一个实现 INotifyPropertyChanged 的​​类时,是否可以将实现公开为公共方法?

例如,如果我在一个类上有一个名为“Sum”的属性,并且我希望在 UI 中单击一个按钮来更新总和,那么最好的方法是什么?

下面是一些伪代码来说明我的意思

classinstance.NotifyPropertyChanged("Sum");
...
public Sum { 
   get { return x + y + z; }
}

【问题讨论】:

    标签: inotifypropertychanged


    【解决方案1】:

    在 .Net 中,引发事件的方法的首选做法是将方法声明为受保护的,以便它只能由派生类调用(这是因为只有声明事件的类才能引发它。为了要从派生类引发事件,需要一个方法来引发事件)。

    例如...

    protected void OnPropertyChanged(string propertyName)
    {
        var handler = this.PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
    

    然后由属性设置器中的类(或派生类)调用此方法,以指示属性已更改,如下所示...

    public object MyProperty
    {
        get { return _myProperty; }
        set
        {
            _myProperty = value;
            OnPropertyChanged("MyProperty");
        }
    }
    

    然后其他对象可以订阅此事件,并且每次MyProperty 属性更改时都会收到通知。

    现在,回答您关于OnPropertyChanged 方法是否可以公开的问题。答案是肯定的,但你应该问问自己为什么会这样。

    为什么另一个类会知道某个属性何时发生更改,以便它可以调用该方法?如果它已经“知道”属性何时更改,那么您首先不需要订阅属性更改事件!只有类本身应该“知道”它自己的属性之一何时发生了变化。

    在您的示例中,您通知属性“sum”已更改。但事实并非如此。事实上,您的代码甚至不允许在其自己的类之外更改该属性。

    我怀疑您可能需要某种方式来通知 sum 属性需要重新评估,因为依赖属性已更改。如果是这种情况,那么您需要在依赖属性更改时引发属性更改事件。

    想象一下,对前面显示的“MyProperty”属性的更改也意味着“Sum”已更改,然后将按如下方式处理:

    // This property is used by the 'sum' property so if this changes
    // clients need to know that 'sum' has also changed.
    public object MyProperty
    {
        get { return _myProperty; }
        set
        {
            _myProperty = value;
            OnPropertyChanged("MyProperty");
            OnPropertyChanged("Sum");
        }
    }
    

    【讨论】:

      【解决方案2】:

      至于实现 base 更漂亮:

          public abstract class NotificationObject : INotifyPropertyChanged
          {
              public event PropertyChangedEventHandler PropertyChanged;
      
              protected void RaisePropertyChanged<T>(Expression<Func<T>> me)
                  => RaisePropertyChanged((me.Body as MemberExpression)?.Member.Name);
      
              protected virtual void RaisePropertyChanged(string propertyName)
                  => PropertyChanged?.Invoke(this, propertyName);
          }
      

      https://msdn.microsoft.com/en-us/magazine/mt736453.aspx也值得查找

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-09-05
        • 2014-12-21
        • 2010-12-23
        • 2010-10-14
        • 2023-03-19
        • 2010-11-03
        • 2010-11-26
        • 2016-07-08
        相关资源
        最近更新 更多