Viewmodel-first: "generally to be avoided"?

Topics: Prism v4 - Silverlight 4
Sep 1, 2010 at 3:32 PM

I found some of the guidance in the Prism 4 .chm a little strange (in Chapter 5: Implementing the MVVM Pattern, under "Construction"):

It is also possible to employ this approach the other way round – i.e. for the view model to explicitly instantiate its corresponding view. However, this leads to numerous difficulties and is generally to be avoided. Specifically, this approach creates an explicit type dependency between the view model and a specific view implementation making it difficult to dynamically replace the view with an alternate one, either at run-time or at design-time.

I don't think this has to be true at all. Much of the advice I've seen involves the ViewModel having either a property of type "object", or of something like "IView", which is either a decorator interface, or (even better) an interface with a set-only property called DataContext or ViewModel. All the view has to do is implement the setter in codebehind and set DataContext = value, which is no worse than creating a property in the View's codebehind used to import a viewmodel. The viewmodel can use a container to get a hold of a view via a loosely-coupled contract name or interface name and store it as an IView.

Plus, with d:DataContext, d:DesignInstance and d:DesignData, it seems that all of the Blendability problems that used to pop up with every strategy besides simple view-first first have been solved.

Sep 2, 2010 at 11:25 PM

You are correct, the wording is overly strong, especially considering all the view model-first samples in Prism 2 and prior do exactly what you are describing - decouple the view model from the view concrete type through an interface and use dependency injection to provide the instance.

The real downside to the view model first approach that the docs should be pointing out is a lack of Blendability - the view doesn't know about the properties exposed by its data context, so you can't leverage the VS and Blend design time data tools as well. Additionally, it locks a view model into supporting only a single view contract, and it is not infrequent that a single view model may be able to support more than one view type (i.e. a summary and a details view). It is also one more dependency that needs to be mocked out when testing the view model, whereas you usually don't write unit tests against the view so there is not the same concern of substitutability when the view has a ref to the view model as there is when the roles are reversed.

I'll work with the team to try to clean up that language in that section.

Thanks

Sep 2, 2010 at 11:57 PM

Thanks for the response Brian.

The d: properties are powerful and I think they fix a lot of problems with Blendability regardless of how one chooses to wire up views and viewmodels, but it seems like it's always mentioned as a secondary option. Why is this? Blend even provides first-class support for it.

Creating a designer-only viewmodel or design data for d: binding may take a little bit more work up front, but it actually provides a clean separation between design time and runtime that you don't get when you try to acheieve Blendability with your real run-time viewmodel. Using the real viewmodel for design-time support ends up polluting it with scattered IsInDesignTool checks, sample data loaders, and added default constructors specifically to support the designer.

Sep 3, 2010 at 11:50 PM

I don't disagree for a second with what you are saying, and am in the process of updating the docs, so will try to include some of what you are suggesting here as what you need to do if you choose view model first. I'm definitely removing the "to be avoided" part. Really it comes down to a matter of preferences and Blendability is a spectrum of capability, not an on/off switch. Either way you put some stuff in place to make the designer happy and fully functional.