使用MVVM模式时,与属性更改相关的代码是应该放入setter还是事件?

寻找有关放置代码的位置的指导,这取决于对属性的更改。

例如,我有一个视图模型,用于保存应用程序设置的状态

public SettingsViewModel(ISettingsRepository settings) { _settings = settings; // ... } 

对于设置属性的每次更改,我们必须将此更改持久保存到存储库,并且在某些属性上,其他属性会受到影响,因此需要其他代码。

我开始只是将这个逻辑添加到setter

 public ProjectCollection Projects { get { return _projects; } set { if (_projects == value) return; _projects = value; RaisePropertyChanged("Projects"); // Extra work needed when collection of projects change _settings.SaveProjects(_projects); Startable = _projects != null && _projects.Count > 0; } } 

但随后交换了为INotifyPropertyChanged连接PropertyChanged事件并从属性setter中删除了其他代码

 public SettingsViewModel(ISettingsRepository settings) { _settings = settings; // ... PropertyChanged += onPropertyChanged; } void onPropertyChanged(object sender, PropertyChangedEventArgs e) { switch (e.PropertyName) { case "Projects": _settings.SaveProjects(Projects); Startable = Projects != null && Projects.Count > 0; break; // ... } } public ProjectCollection Projects { get { return _projects; } set { if (_projects == value) return; _projects = value; RaisePropertyChanged("Projects"); } } 

在setter中设置逻辑意味着编写更少的代码,错误地将错误的属性名称连接错误的机会更少(unit testing应该选择这个)并且稍微快一点,尽管可能微不足道。

将逻辑连接到事件似乎是一种更易于维护的方法,只要方法被恰当地命名,就应该更容易遵循代码,并且意味着除了设置属性之外,setter不做其他工作。 我猜它也可以提供更多的灵活性,使用上面的例子,如果需求发生变化,以便从另一个事件发生持续的更改,例如“保存”按钮,而不是单击属性更改,那么代码应该更容易更改。

我很欣赏这是一个主观的问题,但我是MVVM模式的新手(尽管我认为它可能适用于任何setter逻辑?)所以我在寻求其他方法之前寻找其他原因。 谢谢!

在决定放置哪些代码时,请记住: ViewModel用于向View显示数据 。 它可以稍微按摩或操纵数据(当然 – 在某种程度上改变一个颜色可以被认为是非常好的)。 ViewModel对UI没有任何了解,也不知道有关保存数据的任何信息。

属性设置器应该尽可能简单,如果有任何依赖它们的话,它们应该通知(主要是这种情况 – VM用于绑定)。 这意味着使用OnPropertyChanged()事件处理程序的第二个示例是比第一个示例好得多的选项。

但是,它仍然对我的喜好太了解 。 我会提出模型可以订阅的事件,让模型完成工作。 ViewModel应该只是说“嘿,我的数据已经改变了,我不关心你对它做了什么,但我已经告诉过你这样做你喜欢做什么” 。 然后,模型可以立即保存,或者在持久化数据之前进行更多更改。