是的,坚持一分钟MVVM焦点,有少数可能发生线程的场景:
与往常一样,为简单起见,我们有一个Model类,ViewModel类和View类。 Model有一个Collection和一个字符串属性。
1)用户触发长时间运行的后台任务。视图触发ViewModel。可以使用ViewModel轻松管理,例如,使用BackgroundWorker
2)线程更新模型,ViewModel通过模型更改通知。
之前我们已经讨论过使用INotifyChanged来通知从Model到ViewModel的更改。 DependencyProperty系统似乎为您编组这些正确的线程。
对于ObservableCollections,这不起作用。因此,如果我的模型的公共面是单线程的(不喜欢,模型为什么要知道线程),或者我会在ViewModel中复制模型的某些部分(例如上面的Collection)以确保对模型进行修改正确的线程?
我想我已经回答了我自己的问题。也许不是。我的模型确实知道线程,所以也许使用科林早些时候提出的IMarshalInvoker想法来标记它们是否有礼貌?
我的一些问题是我认为MVVM是另一个MVC变种,而且从历史上看,我很乐意互相使用像MVP,MP,MVC这样的术语,因为我知道GUI技术有什么用处(通常在V端的winforms)。当我说MVVM时,我特别在寻找有关WPF和WPF特定弱点的实用建议。我希望这能解释我的问题的性质以及我问他们的原因。
答案 0 :(得分:6)
我认为在模型中全面展开并实现集合ObservableCollection
并不是一个好主意,因为这会以一种仅对WPF有用的方式“污染”您的模型。
INotifyPropertyChanged
没问题,因为:
所以,我建议不让你的模型了解线程。让您的ViewModel了解线程,如下所示:
class Model {
List<Widget> Widgets { get; private set; }
}
class ModelViewModel {
ObservableCollection<Widget> Widgets { get; private set; }
ModelViewModel(Model model) {
this.Widgets = new ObservableCollection<Widget>(model.Widgets);
}
}
如果Widget
是引用类型并实现INotifyPropertyChanged
(大约100%的时间都是这样),那么大部分时间都可以实现:
model
本身,并会立即反映绑定仍然存在不会直接向model
更新集合(添加和删除项目)的问题。但可以安排:
ModelViewModel(Model model) {
this.Widgets = new ObservableCollection<Widget>(model.Widgets);
this.Widgets.CollectionChanged += this.PropagateChangesToModel;
}
void PropagateChangesToModel(object sender, NotifyCollectionChangedEventArgs e) {
// do what the name says :)
}
最后,您需要让ObservableCollection
在从工作线程更新时发挥出色。这是WPF的一个非常常见的问题,我建议您回答这个问题的解决方案:ObservableCollection and threading。