Expose Model list to several ViewModels - and keep them in sync
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&l开发者_StackOverflowt;> 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.
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.
精彩评论