MVVM: Thin ViewModels and Rich Models
I'm continuing to struggle with the MVVM pattern and, in attempting to create a practical design for a small/medium project, have run into a number of challenges. One of these challenges is figuring out how to get the benefits of decoupling with this pattern without creating a lot of repetitive, hard-to-maintain code.
My current strategy has been to create 'rich' Model classes. They are fully aware that they will be consumed by an MVVM pattern and implement INotifyPropertyChanged, allow their collections to be observed and remain cognizant that they may always be under observation. My ViewModel classes tend to be thin, only exposing properties when data actually needs to be transformed, with the bulk of their code being RelayCommand handlers. Views happily bind to either ViewModels or Models directly, depending on whether any data transformation is required.开发者_如何学JAVA I use AOP (via Postsharp) to ease the pain of INotifyPropertyChanged, making it easy to make all of my Model classes 'rich' in this way.
Are there significant disadvantages to using this approach? Can I assume that the ViewModel and View are so tightly coupled that if I need new data transformation for the View, I can simply add it to the ViewModel as needed?
I think INotifyPropertyChanged on your model is only useful when you're expecting it to be operated on by your VM and external "forces" simultaneously.
I'm personally a supporter of POCO models. Putting any framework-specific scaffolding into my model would make me worry. When you put an event into your model class you have to consider carefully possible issues with your model's life-cycle, serialization, storage etc. For example what happens if you recreate your object from data source and old INotifyPropertyChanged subscriptions are now invalid?
Similarily better place for ObservableCollection is in the VM, which can consume an IEnumerable datasource, and present to the view only selected or ad hoc filtered items.
I consider this to be the pragmatic approach - we have followed this pattern successfully in the past.
The basic premis was to bind directly to a model that implements INotifyPropertyChanged for most read-only data, and then add extra properties to the viewmodel for view specific stuff that needs to be transformed (as you suggested). For non read-only properties, we found it easiest the create viewmodel entries (generally of type string) as this allows client-side validation to be added easily in the viewmodel.
Disclaimer - I am not an expert -
I do not put INotifyChanged on my Models. I had done this at first but came to the simple realization that INotifyChanged is really only practical for notifying the UI so I only put INotifyChanged on my ViewModels now. This has made it easier to control the number of "RaisePropertyChanged"... My views never reference a Model directly.
I'm working on my first MVVM project yet on my 3rd major refactor :P
I agree that there will be tight coupling between the View and ViewModel. But this can be alleviated to some extent by using IValueConverters whenever possible to do transformations.
I try to keep my business logic in my ViewModel. Also, I use the Viewmodel to change the shape of my Model to fit that which the View might expect.
精彩评论