11

也许这里已经有这样的问题,但我没有找到。

我有 MVVM 应用程序,在我的应用程序中,ViewModel我必须对某些属性的更改执行一些额外的操作(例如,如果View更改它们)。您认为哪种方法更好,为什么?

1st - 添加AdditionalAction对 setter 的调用

public class ViewModel: INotifyPropertyChanged
{
  private int _MyProperty;

  public int MyProperty
  {
    get { return _MyProperty; }
    set
    {
      if (_MyProperty == value) return;
      _MyProperty = value;
      RaisePropertyChanged(() => MyProperty);

      // --- ADDITIONAL CODE ---
      AdditionalAction();
    }
  }
}

2nd - 自行订阅 INotifyPropertyChanged

public class ViewModel: INotifyPropertyChanged
{
  public ViewModel()
  {
    // --- ADDITIONAL CODE ---
    PropertyChanged += OnPropertyChanged;
  }

  private int _MyProperty;

  public int MyProperty
  {
    get { return _MyProperty; }
    set
    {
      if (_MyProperty == value) return;
      _MyProperty = value;
      RaisePropertyChanged(() => MyProperty);
    }
  }

  void PropertyChanged(object sender, PropertyChangedEventArgs e)
  {
    // --- ADDITIONAL CODE ---
    if (e.PropertyName == "MyProperty")
      AdditionalAction();
  }
}

想象一下,我没有性能问题或 10'000 个对象。它只是 View 和 ViewModel。什么是更好的?第一个代码“更小”并且开销更少,但第二个(在我看来)更清晰,我可以将代码片段用于自动生成属性的代码。甚至更多 - 在第二种情况下,我可以在事件处理程序中编写如下内容:

On.PropertyChanged(e, p => p.MyProperty, AdditionalAction);

On类助手在哪里。

那么,您认为什么更好,为什么?

更新:

好的,看起来我找到了一种方法:

第三 - 在 RaisePropertyChanged 中添加“扩展点”:

public class NotificationObject : INotifyPropertyChanged
{
  void RaisePropertyChanged(Expression<...> property)
  {
    // ... Raise PropertyChanged event
    if (PropertyChanged != null)
      // blah-blah

    // Call extension point
    OnPropertyChanged(property.Name);
  }

  public virtual OnPropertyChanged(string propertyName)
  {
  }
}

public class ViewModel: NotificationObject
{
  private int _MyProperty;

  public int MyProperty
  {
    get { return _MyProperty; }
    set
    {
      if (_MyProperty == value) return;
      _MyProperty = value;
      RaisePropertyChanged(() => MyProperty);
    }
  }

  override OnPropertyChanged(string propertyName)
  {
    if (propertyName == "MyProperty")
      AdditionalAction();
  }
}

这样我们不使用事件,而是从同一个“扩展点”调用所有“附加操作”。“所有添加操作的一个地方”比“不透明的工作流程”更好吗?

4

2 回答 2

3

肯定会选择第一种方法:

  • 天气晴朗
  • 它的流程和意图很明确
  • 它避免了奇怪的(imo)自我订阅

第二个允许您使用自动生成的属性的“好处”不值得第一个案例的执行流程清晰,imo。

希望这可以帮助。

于 2012-05-04T14:58:19.957 回答
3

这是“通常”的模式。这允许您将特定于属性的代码放入 OnX 方法中,并允许派生类执行相同的操作。不需要大的 switch 语句,除非您当然是外部侦听器,但这对于 INotifyPropertyChanged 的​​课程来说是正常的。

public class NotificationObject : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    protected void FirePropertyChanged(PropertyChangedEventArgs e)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
            handler(this, e);
    }
}

public class ViewModel : NotificationObject
{
    private int _MyProperty1;
    public int MyProperty1
    {
        get { return _MyProperty1; }
        set
        {
            if (value != _MyProperty1)
            {
                _MyProperty1 = value;
                OnMyProperty1Changed(new PropertyChangedEventArgs("MyProperty1"));
            }
        }
    }

    protected virtual void OnMyProperty1Changed(PropertyChangedEventArgs e)
    {
        FirePropertyChanged(e);
    }

    private int _MyProperty2;
    public int MyProperty2
    {
        get { return _MyProperty2; }
        set
        {
            if (value != _MyProperty2)
            {
                _MyProperty2 = value;
                OnMyProperty2Changed(new PropertyChangedEventArgs("MyProperty2"));
            }
        }
    }

    protected virtual void OnMyProperty2Changed(PropertyChangedEventArgs e)
    {
        FirePropertyChanged(e);
    }
}
于 2012-05-04T15:53:23.780 回答