我对有关数据访问的MVVM应用程序(以前称为WinRT,现在针对UWP)的体系结构感到困惑。我不确定如何在UI上传播更改以及在何处访问数据层。
这是基本架构:
:模型的ViewModel:环绕模型并公开属性。有时我将控件的内容(例如TextBoxes)双向绑定(bind)到属性。然后,设置者将访问数据层以保留此更改。
我现在在这个架构上遇到几个问题:
问题1:在几个宫殿的屏幕上可以代表一种模型。例如,主从 View 显示一个类型的所有可用实体的列表。用户可以选择其中之一,其内容将显示在详细 View 中。如果用户现在在详细 View 中更改了属性(例如,模型的名称),则更改应立即反射(reflect)在主列表中。最好的方法是什么?
问题2:我也不确定我访问数据的位置是否选择得当。 PageViewModels变得非常复杂,基本上可以完成所有操作。而且所有ViewModel都需要我的体系结构的数据层知识。
我一直在考虑使用sqlite-net取消数据访问,而改用Entity Framework 7。 是否可以解决上述问题,即当我使用相同的上下文时,它可以保证一个模型的对象身份吗?我还认为这将简化ViewModel,因为我很少需要读取操作,因为这是通过导航属性完成的。
我也一直想知道在MVVM应用程序中使用双向数据绑定(bind)是否是个好主意,因为它需要属性 setter 调用数据访问层才能保留更改。仅执行单向绑定(bind)并通过命令保留所有更改是否更好?
如果有人可以对我的体系结构发表评论并提出改进建议或指向关注我的问题的MVVM体系结构的好文章,我将非常高兴。
最佳答案
- Have one ViewModel for the model? I don't think this makes much sense, as the master list needs only very little logic, and the detail view much more.
ViewModel不依赖于模型。 ViewModel使用该模型来满足 View 的需求。 ViewModel是 View 的单接触点,因此无论ViewModel需要提供什么 View 。因此它可以是单个模型/多个模型。但是您可以将单个ViewModel分解为多个子ViewModel,以简化逻辑。可以将其类似的详细信息 Pane 分为具有自己的 View 模型的用户控件。您的母版页上将只有一个窗口,它将托管此控件,而MasterViewmodel会将职责推送到子ViewModel。
- Let the model implement INotifyPropertyChanged and thus propagate the change to the ViewModels? The problem I have with this, is that the data layer currently doesn't guarantee that the objects it returns for two read operations on one model id are identical - they just contain the data read from the database and are newly created when they are read (I think that's the way sqlite-net works). I'm also not really sure how to avoid memory leaks happening because of all the PropertyChanged event subscriptions from the ViewModels. Should I implement IDisposable and let the PageViewModel call its children's Dispose() method?
危险不是使用
INotifyPropertyChanged
,而是您正确地表示了订阅和取消订阅。无论何时需要订阅任何事件,不仅需要INotifyPropertyChanged
,还需要使用IDisposable
取消订阅自身及其子ViewModel。我在您描述的数据层上不清楚,但是如果它发布属性更改事件以进行任何修改,那么使用INotifyPropertyChanged
不会出现任何问题。3.I currently have a DataChanged event on my data access layer. It is called whenever a create, update or delete operation occurs. Each ViewModel that can be displayed simultaneously listens to this event, checks whether the changed model is the one its the ViewModel for and then updates its own properties. Again I have the problem of the memory leak and this becomes slow, as too many ViewModels have to check whether the change is really for them.
如前所述,如果您为所有模型正确处理订阅/取消订阅,则无需担心INotifyPropertyChanged的性能问题。但是,可能增加该问题的是您为请求数据而对数据库进行的调用次数。您是否考虑过将Async ... Await用于数据访问层,这将不会阻止UI进行任何正在发生的更新。即使数据更新很慢, react 性UI也不被数据调用阻塞是更好的选择。
因此,请尝试添加在DAL层上抽象的数据访问服务,并提供一种异步方法来访问数据。也看看Mediator Pattern。这可能会有所帮助。
I'm also not sure whether the place I access data is really well chosen. The PageViewModels have become extremely convoluted and basically do everything. And all ViewModels require knowledge of the data layer with my architecture.
我看到2个主要问题,
I've been thinking of scrapping data access with sqlite-net and using Entity Framework 7 instead.
没有确凿的证据,请勿尝试用EF替换sqlite-net。您需要先评估应用程序的性能,然后再尝试进行如此大的更改。如果问题出在代码而不是正在使用的组件上,该怎么办。首先尝试解决上述问题,然后可以通过接口(interface)隔离DAL层,并在需要时进行替换。
I've also been wondering whether having two way databinding is good idea at all in a MVVM application, as it requires the property setter to call the data access layer to persist the changes. Is it better to do only one-way binding and persist all changes through commands?
如果您每次每次对字段/进行更改时都直接调用数据库,那么这将是一个问题。然后,您应该具有数据模型的副本,并且仅在单击“保存”按钮时才保留更改。
关于c# - MVVM体系结构: one model - several view models + place for data access,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35392335/