关于MVVM应用程序(曾经是WinRT,现在针对UWP)的架构和数据访问,我感到有些困惑。我不确定如何跨UI传播更改以及在哪里放置数据层访问。
以下是基本体系结构:
- 模型层: 包含仅具有自动属性的模型(没有导航属性引用其他模型,只有ID;因此它们基本上只是数据库的表示)。它们不实现INotifyPropertyChanged接口。
- 数据访问层: 使用sqlite-net存储模型到数据库的仓储。它公开基本的CRUD操作。它返回并接受模型层的模型。
- 视图模型:
- 模型的视图模型: 它们包装模型并公开属性。有时我使用双向绑定将控件(例如TextBoxes)内容绑定到属性。然后,setter访问数据层以持久化此更改。
- 视图的页面视图模型: 它们包含上述的视图模型和命令。许多命令已变得非常长,因为它们执行数据访问、执行特定于域的逻辑并更新PageViewModels属性。
- 视图 (页面): 它们绑定到PageViewModels,并通过DataTemplate到模型的ViewModle。有时使用双向数据绑定,有时使用命令。
我现在对这个架构有几个问题:
问题1: 一个模型可以在屏幕上多次呈现。例如,一个主-详细视图,显示该类型的所有可用实体列表。用户可以选择其中之一,并在详细视图中显示其内容。如果用户现在更改了详细视图中的属性(例如,模型的名称),则应立即在主列表中反映出更改。最佳方法是什么?
- 一个ViewModel用于模型?我认为这没有多大意义,因为主列表只需要非常少的逻辑,而详细视图需要更多。
- 让模型实现INotifyPropertyChanged并将更改传播到ViewModels?我对此的问题是,数据层当前不能保证为一个模型ID进行两个读操作返回的对象是相同的-它们只包含从数据库中读取的数据,并且在读取时新创建(我认为SQLite-net的方式就是这样)。我也不确定如何避免由于ViewModels的所有PropertyChanged事件订阅而发生内存泄漏。我应该实现IDisposable,并让PageViewModel调用其子级的Dispose()方法吗?
- 我目前在我的数据访问层上有一个DataChanged事件。每个可以同时显示的ViewModel都会侦听此事件,检查更改的模型是否为其ViewModel,然后更新自己的属性。再次出现了内存泄漏的问题,而且这变得很慢,因为太多的ViewModel必须检查更改是否真的是针对它们的。
- 还有其他方法吗?
问题2:我也不确定我访问数据的位置是否真的选择得很好。PageViewModel已经变得非常复杂,基本上做了所有事情。我的架构中所有ViewModel都需要了解数据层。
我一直在考虑放弃使用sqlite-net的数据访问,改用Entity Framework 7。这会解决上述问题吗?即当我使用相同的上下文时,它是否保证一个模型的对象标识?我还认为它会简化ViewModels,因为我很少需要读取操作,因为这是通过导航属性完成的。
我还在想MVVM应用程序中是否有双向数据绑定的好主意,因为它要求属性设置器调用数据访问层以持久化更改。仅进行单向绑定并通过命令持久化所有更改是否更好?
如果有人能评论我的架构并提出改进建议或指向关注我的问题的MVVM架构的好文章,我会非常高兴。