views:

247

answers:

5

I'm using MVVM with Prism and Silverlight. I have multiple different views of one model. As I am writing more views their ViewModels seem to duplicate a lot of common code related to handling this one model. Rather than repeating the same common code in all the VMs I am tempted to push it back into the model (which would probably mix concerns too much). Or maybe into some common ViewModel base class? Or perhaps my VMs need a 2nd level of "shared VM" between them and the model? This single shared instance, 2nd-level-VM would consolidate the behavior and state shared by the multiple regular VMs.

Any comments about these issues and possible approaches?

Thanks, Alan Cobb

+1  A: 

If the common code can be shared by all ViewModels, then it's worth putting it into a base ViewModel type.

If the common code is only shared by ViewModels that interact with a particular Model, then a "shared" ViewModel is the way to go.

Cameron MacFarland
A: 

I've used inheritance for ViewModels in the New York Times Silverlight Kit successfully to reduce replicated code. Look at the CommunityRecentComments and its parent class CommunityBase for an example.

Michael S. Scherotter
A: 

Most "base ViewModel" classes in the variety of MVVM frameworks tend to contain the support for INotifyPropertyChanged and usually some sort of support for dispatching back to the UI thread.

Beyond that I think that if you have a number of ViewModels that share functionaltiy that should be into a base class, the more I use this pattern the more I find myself using a rather shallow hierarchy of ViewModels, a base ViewModel for code common to all view models and typically another base class under that for common functionality in that area of the UI. Usually common commands or where the UI is sharing elements.

ViewModelBase -> ProductsViewModelBase -> NewProductViewModel

Nigel Sampson
A: 

In SoapBox Core, which is fully MVVM, I defined an IViewModel interface, and an AbstractViewModel base class which, as Nigel said, just implements INotifyPropertyChanged. (Note that SoapBox Core is WPF, not Silverlight, but in this case it's not a big deal. I've done some similar Silverlight work as well.)

Then I defined more interfaces (like IMenuItem) that inherit from IViewModel and more abstract classes that provide a basic implementation of those interfaces.

Now, that accounts for the whole ViewModel tree, but as you said, there's also the Model tree. I've spent almost a year working with MVVM now and here's my big epiphany: Don't write a Model. If you're building the application from the ground up, just put everything in the ViewModel, otherwise you end up duplicating a ton of code.

The only cases where I bothered having a Model was when I was using a 3rd party library that didn't implement INotifyPropertyChanged and therefore wasn't easily bound to. I believe that auto-generated code for entity frameworks might fall in here as well, but I noticed that some entity frameworks now give you the option of implementing INotifyPropertyChanged in the entities themselves.

Seriously, we should rename it the ViewModel pattern and be done with it. :)

Scott Whitlock
A: 

Thanks for the comments guys. I probably should have told you more about the specific "shared" VM code in question.

I can see putting some future code in a VM base class, but the particular "shared" code I'm looking at seems to belong in an INotifyPropertyChanged implemented by the model itself. This is partly based on this other thread.

I don't think this violates SoC, because the model is inherently dynamic. Some of its properties are only valid at certain times. That dynamic nature of the model is not just something that's important for the UI, a proper unit-test would also care about it. Hence this model seems to need an INotifyPropertyChanged.

Any comments on that?

Thanks, Alan Cobb

Alan Cobb
It's better to update your original question than to add such an answer...
Yacoder