MVVM、集合和ORM

5
我试图使用MVVM设计模式,结合WPF和Entity Framework创建一个简单的应用程序。如果类之间松散耦合,则一切都很顺利,但是如果我有两个模型类:Customer和Address,且Customer具有Address的集合。
现在,对于这些类,我需要创建两个VM类-CustomerVM和AddressVM。CustomerVM应该具有AddressVM对象的ObservableCollection。对这些VM类进行的每个更改(包括对CustomerVM和AddressVM的所有CRUD操作)都需要反映在模型类中-这就是为什么我最终编写了大量代码的原因,例如订阅ObservableCollection的更改事件,如果添加了新对象,则添加一个新对象到模型...等等...
怎么办?使用MVVM时是否常见?我做得对吗?如何减少所需的代码量以处理此类简单的类层次结构?是否有任何框架可以创建基本的VM类,并且与层次结构中的其他类“良好地运作”?如果类关系变得更加复杂,该怎么办?
简而言之:
如何在vm集合中反映对模型集合所做的更改:
CustomerVM1.AdressesVM.Add(new AddressVM{City="New York"}) 

应该导致相当于:

Customer1.Adresses.Add(new Address{City="New York"})

另外还有一个相反的问题 - 如何将对集合所做的更改反映到模型中以包含在视图模型中,但我更感兴趣的是第一个问题,因为它具有更实际的应用,而且vm对象在大多数情况下可以简单地重新创建。

2个回答

1

你可能会对WPF应用程序框架(WAF)BookLibrary示例应用程序感兴趣。它展示了如何将实体框架和MVVM结合使用。

简短提示:它不为每个实体类创建包装器ViewModel,而是为视图创建ViewModel类。


0

当你试图弄清楚如何将ViewModel中的ObservableCollection与Model中的普通集合同步时,你遇到了完全相同的问题。 ObservableCollection非常好用,因为View可以绑定它并在集合更改时自动更改。不幸的是,你只是将同步问题下移了一级。

一个选择是在任何地方都使用ObservableCollections,甚至在Model中也是如此。这不是很干净的架构,因为MVVM不应对Model提出任何要求。

我解决这个问题的方法是引入Presenter,所以我的架构看起来像这样:

View -> ViewModel <-> Presenter <-> Model

此外,我将我的ViewModels设计为简单模型。以下是典型的用户操作从开始到完成的过程:

  1. 用户点击“添加”按钮。
  2. ViewModel会引发一个事件,Presenter订阅该事件,或调用Presenter的方法,或在ViewModel构建时提供给Presenter的回调。它实质上是将操作委托给Presenter。
  3. Presenter调用Model的Add方法。
  4. Model响应Add调用,更新所有相关状态,包括普通集合。
  5. Presenter在执行了对Model的操作后,从Model中读取新状态并将状态写入ViewModel。绑定会处理视图的同步。

因此,在您的情况下,Presenter可以订阅ViewModel中ObservableCollection的CollectionChanged事件,当它发生变化时,通过在Model上调用Add来响应该事件。另一方面,当Presenter正在处理调用Model的其他用户操作(因为Presenter处理所有与Model的交互),则它知道必须将更改传播到ViewModel中的ObservableCollection。

在我的代码中,我简化了情况...在 Presenter 执行 Model 的每个用户操作后,我将所有相关状态在 Model 中适用的位置直接复制到 ViewModel 中。你正在做比你需要的更多的工作,但在典型的 CRUD 应用程序中,没有明显的性能问题。如果我拥有一个非常大的对象集合,性能可能会成为一个问题,那么我会下降到更细粒度的同步(仅更新更改的实体),以换取更复杂的逻辑。

非常感谢您提供的出色答案。这确实是解决问题的一种方式,但在我看来,这并不能真正让您编写更少的代码 - 它只是更清晰的方法。仍然需要 Presenter 这个层次,事情变得比它们本应该的更加复杂。 - kubal5003
昨天我在考虑做一些类似于“简化版”MVVM的事情 - 而不是创建VM类,我想通过使用部分类来扩展模型类。现在,对于我需要的每个属性,我都可以创建另一个封装旧属性的属性 - 与MVVM中相同。对于普通的集合,我可以创建一个仅实现INotifyCollectionChanged并使用普通的集合进行存储的包装器集合。你觉得呢? - kubal5003
我还在考虑的另一件事情是,也许可以创建一个通用集合,比如MyCollection<VMClass,MClass> -> 这个集合应该知道有关模型<->视图模型交互的所有内容,并能够处理您在Presenter中所做的所有操作。如果编写得好,它可以在任何地方重复使用。 - kubal5003

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接