将模型列表公开给多个视图模型 - 并保持它们同步
我知道有很多关于如何处理 Model 和 ViewModel 集合的讨论,并且不同各方已经提出了很多“同步器”解决方案以及 BLINQ、CLINQ、MVVM 包装套件等。我仍然没有掌握这一点,我希望找到一个很好的解决方案来解决我当前项目中的问题,如此处所述。主要区别是我有几个公开相同模型数据的 ViewModel。
我有一个相当简单的 WP7 项目,我使用 MVVM Light 和 Messenger 类作为中介。有一个从隔离存储中获取的项目列表。几个(四个)不同的视图以不同的形式显示该数据。所有这三个都可以以不同的方式修改数据(ViewModel 包含更改的逻辑 - 而不是视图)。
如果我选择 ObservableCollection<>在包装 List<> 的 ViewModel 中在 Model 中,更改数据的 ViewModel 会同时修改其自己的 ObservableCollection<> 和 ObservableCollection<> 。和列表<>在模型中。如果我有一个 ViewModel 从模型中公开列表,这可能就是我会做的,这样 ViewModel 就可以保持自身和模型是最新的。然而,在这个项目中,我有多个消费者使用同一个列表,并且 ObservableCollections<> 。其他 ViewModel 中的内容不会被更新。为了解决这种情况,我可以使用中介模式并通知其他 ViewModel 项目集合已更改,以便他们可以刷新它。我可以通过发送描述更改的消息来获得一些性能,并且所有其他 ViewModel 都可以在内部执行相同的更改。然而,这需要我在一个中心位置共享一些逻辑,以避免在多个不同的 ViewModel 中重复添加/删除/更改逻辑。
由于我需要将更改传达给其他 ViewModel,因此我决定采用另一条路线。我将 ObservableCollection<> 更改为到标准列表<>并删除了处理更改通知的代码。所以ViewModel和Model都有List<>对象。是否将模型列表包装在 ViewModel 中并不重要,我可以直接在 ViewModel 中公开 Model.Items 来简化事情(也许还可以获得一些性能)。现在,当某些 ViewModel 更改某些内容时,它将直接在模型中更改它,然后发送一条消息,表明项目集合已更改,并且所有 ViewModel 都会引发集合属性更改的属性通知。
这似乎工作正常。但我有两个担忧:
- 这是一个好的解决方案还是以后会遇到问题?我是否正在做一些完全反对 MVVM 的事情,从长远来看会损害代码库?
- 我感觉更改通知有时有点慢。也就是说,当我“单击”列表中的某个项目时,列表更新之前会有一小段延迟。我不确定这是否是因为我在多个视图中刷新整个 i 列表或因为调解器延迟。
非常感谢任何想法/评论。
I know that there are alot of discussions about how Model and ViewModel collections should be handled and alot of "syncher" solutions have been proposed from different parties along with BLINQ, CLINQ, MVVM Wrapper Kit etc. I'm still not grasping this and I would like to find a good solution to the problems in my current project as described here. The main difference is that I have several ViewModels that expose the same Model data.
I have a rather simple WP7 project and I'm using MVVM Light and the Messenger class as mediator. There is a list of items which is fetched from isolated storage. Several (four) different views show this data in different forms. All three of these can modify the data in different ways (the ViewModel contains the logic for the change - not the view).
If I go with a ObservableCollection<> in the ViewModel that wraps a List<> in the Model then the ViewModel that changes the data modifies both its own ObservableCollection<> and the List<> in the Model. This is probably what I would do if I had a single ViewModel expose the List from the Model, that way the ViewModel could keep itself and the Model up-to-date. However, in this project I have several consumers to the same List and the ObservableCollections<> in other ViewModels will not be udated. To remedy this situation I can use the mediator pattern and notify the other ViewModels that the items collection have changed so they can refresh it. I could gain some performance by sending a message describing the change and all the other ViewModels could do the same change internally. This would however require that I share some of this logic in a central place to avoid duplicating add/remove/change logic in several different ViewModels.
Since I need to communicate the changes to the other ViewModels I decided to go another route. I changed ObservableCollection<> to a standard List<> and removed the code for handling change notification. So both the ViewModel and the Model have List<> objects. It doesn't really matter if I wrap the Models List in the ViewModel or not, I can expose Model.Items directly in the ViewModel to simplify things (and perhaps gain some perforamance). Now, when some ViewModel change something it will change it directly in the Model and then send a message that the items collection have changed and all ViewModels raises a property notification changed on the collection property.
This seems to work fine. I have two concerns though:
- Is it a good solution or will I get problems later on? Am I doing something completely against MVVM that will hurt the code base in the long run?
- I have a feeling that the change notification is a bit slow at times. That is when I "click" an item in a list there is a small delay before the list is updated. I'm not sure if this is because I'm refreshing the entire i list in several views or because of the mediator delay.
Any thoughts/comments are greatly appreciated.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
跟踪不同的视图模型相互通知更改将导致意大利面条式代码。我目前正在使用一个复杂的 Silverlight 4 桌面应用程序亲自经历这个过程。
我发现的解决方案是拥有一个单独的 ViewModel,其中包含将在其他 ViewModel 之间共享的数据。这样你就只有一个 ObservableCollection - 与你的数据一起驻留在视图模型中的那个。
Keeping track of having different view models notify each other with changes will lead to spaghetti code. I'm currently going through this myself with a complicated Silverlight 4 desktop app.
The solution that I'd found is to have a separate ViewModel that containa the data that will be shared between your other ViewModels. This way you only have one ObservableCollection - the one that resides in the view model with your data.
在这种情况下要做什么的部分决定取决于列表中对象的数量以及您对它们进行的操作量。无论您采用哪种方法,请务必在真实设备上进行彻底测试以验证性能。
也就是说,我倾向于采取您所采取的方法来解决您的问题:
- 它的简单性允许未来的灵活性。
- 由于它的简单性,其他开发人员将来应该能够更容易地理解代码。
正如我之前所说,验证真实设备上的性能以确认是否存在问题。如果这是一个问题,那么在重新构建应用程序之前,先考虑隔离瓶颈并解决它。
Part of the decision on what to do in this situation will depend on the number of objects in your List and the amount of manipulation you are doing to them. Whichever approach you take, be sure to test thoroughly on a real device to verify performance.
That said, my inclination to addressing your problem would be to take the approach you've taken:
- Its simplicity allows for flexibility in the future.
- Due to it's simplicity, other developers should be able to understand the code more easily in the future.
As I said before, verify performance on a real device to confirm if it's an issue. If it is a problem then look at isolating the bottle neck and addressing it, before rearchitecting the app.