MVVM Instantiation Approaches

As a pattern, there's a lot of flexibility and choice available when implementing the Model-View-ViewModel pattern. However, no matter how you go about it, there are a few things you'll have to do:

  • Instantiate the view
  • Instantiate the view model
  • Connect the view to the view model, so that you can bind to it

There are many ways to accomplish this, and different resources on the pattern show different ways. This page discusses some of those approaches, and attempts to give them a name.

I would love to know if you have seen alternative patterns in the wild, and any pros/cons you have experienced using these approaches.

Option 1: Internal creation:

This is the approach I generally start with when introducing the pattern. In this case, the VM is just a private "implementation detail" of the view, while still being testable.

public CalculatorView()
{
    InitializeComponent();
    DataContext = new CalculatorViewModel(); 
}

Option 2: ViewModel as a dependency:

This is what I usually evolve the first example into, so that we can start to talk about DI and the use of containers.

public CalculatorView(CalculatorViewModel viewModel)
{
    InitializeComponent();
    DataContext = viewModel;
}

Then when you navigate to the view (note: you'd probably want to use an IOC container to instantiate these):

var viewModel = new CalculatorViewModel();
var view = new CalculatorView(viewModel);

Option 3: External creation and assignment:

In this approach, the View doesn't even know how its DataContext will be set - our navigation code "peers in" to the view:

var view = new CalculatorView();
var viewModel = new CalculatorViewModel();
view.DataContext = viewModel;

Option 4: ViewModel as a XAML property value:

Instead of code, some people like to use XAML to create and assign the view model:

<UserControl ...>
    <UserControl.DataContext>
        <local:CalculatorViewModel />
    </UserControl.DataContext>

Some choose to just use this at design time, and replace it at runtime, using one of the options above to override the DataContext.

Option 5: ViewModel as a XAML resource:

Some eschew DataContext all together, and go with a resource. This approach worked very well with earlier versions of Expression Blend.

<UserControl ...>
    <UserControl.Resources>
        <local:CalculatorViewModel x:Key="Model" />
    </UserControl.Resources>

    <TextBox Text="{Binding Source={DynamicResource Model}, Path=...}" />

This is also sometimes replaced at runtime using options 1-3, for example:

public CalculatorView(CalculatorViewModel viewModel)
{
    InitializeComponent();
    Resources["Model"] = viewModel;
}

Option 6: A XAML View Model Locator:

Rather than constructing the view model, some use a locator to resolve the ViewModel, while still allowing it to be used as a resource (and thus get a nice design experience). Others use ObjectDataProvider for a similar purpose. This approach has been popularized by MVVM Light:

<UserControl ...>
    <UserControl.Resources>
        <ViewModelLocator x:Key="ViewModelLocator"/>
    </UserControl.Resources>

    <TextBox 
        Text="{Binding Source={DynamicResource ViewModelLocator}, Path=CalculatorViewModel...}" 
        />

Option 7: DataTemplate as views

Some lunatics don't use a real view at all, but instead just use a DataTemplate. These people should not be allowed near sharp objects :-)

<DataTemplate DataType="{x:Type local:CalculatorViewModel}">
    <... />
</DataTemplate>

<!-- Because of the DataType, this will automatically select the template above -->
<ContentPresenter Content="{Binding Path=Model}" />

Option 8: Data Template and View

Similar to 7, this approach uses a data template to select the appropriate view for a given view model, but the view still has its own class. Thanks to Marek, Ian and Daniel Spruce (see comments below) for pointing out this alternative:

<DataTemplate DataType="{x:Type ViewModels:CalculatorViewModel}">
    <Views:CalculatorView />
</DataTemplate>

Personally, I tend to use Option 2 (ViewModel as dependency) if I'm not using a framework, otherwise Option 3 (External creation and assignment). I either forgo designer support or rely on tools such as the newer Blend sample data support, so the other approaches aren't too useful to me. Magellan uses option 3 by default.

Which approach do you use? Do you do something different? Care to share a sample?

Update: I also posted this to the WPF Disciples list - you can see what some of the other disciples had to say here.

A picture of me

Welcome, my name is Paul Stovell. I live in Brisbane and work full time bootstrapping my own product company around Octopus Deploy, an automated deployment tool for .NET applications.

Prior to Octopus Deploy, I worked for an investment bank in London building WPF applications, and before that I worked for Readify, an Australian .NET consulting firm, where I was lucky enough to work with some of the best in the business. I also worked on a number of open source projects and was an active user group presenter. I've been a Microsoft MVP for WPF since 2006.

Daniel Rose
Daniel Rose
08 Jun 2010

Small typo in option 2: CalcualtorViewModel should be CalculatorViewModel.

08 Jun 2010

Thanks Daniel, fixed! :)

08 Jun 2010

Option 1 or 2 for me.

08 Jun 2010

There's another one used in the nRoute framework (nroute.codeplex.com): use attributes to declaratively associate Views with ViewModels, then in the View's XAML use a blend behavior that hooks them up by using these attributes:

[assembly: DefineViewViewModel(typeof(FooView), typeof(FooViewModel))]

...then in FooView.Xaml:

08 Jun 2010

I'm using option 2 as well. With an IoC container.

Marek
Marek
08 Jun 2010

I don't think that Option 7 is lunatic at all ;-)

For example this code

<DataTemplate DataType="{x:Type ViewModels:CalculatorViewModel}">
<Views:CalculatorView />
</DataTemplate>

is almost equivalent to approaches #2 or #3, but all done in 'XAML way'.

08 Jun 2010

I prefer option 2 as well.

Adrian Hara
Adrian Hara
08 Jun 2010

Trying to repost what was sanitized from my previous comment:

<i:Interaction.Behaviors>
    <nRouteBehaviors:BridgeViewModelBehavior/>
</i:Interaction.Behaviors>
08 Jun 2010

I use a variation of the M-V-P pattern that I call PM-V-P. The Presentation Model (PM) is equivalent to the VM in the M-V-VM pattern, except that it only exposes data and fires change events; it contains no logic (the logic is in the presenter).

I typically require the PM to be passed to the Presenter via a constructor along with the view. The presenter "owns" the PM and assigns it to the view when the presenter is run.

Rob
Rob
08 Jun 2010

Caliburn uses option 3. Becuase we favor a VM-First approach, we typically start by getting a VM from the IoC container, then we use a ViewLocator to find a matching view for that VM. Once the view type is determined, it is then either pulled from the container or instantiated normally. Finally, Caliburn sets the DataContext on the view, optionally applies action/binding conventions and plugs the view into the propper location within the UI.

08 Jun 2010

I activate all my views using a Navigate function

Public Sub Navigate(Of T As {FrameworkElement, New})(ByVal Key As String, 
                    ByVal ExtraParam As Object, ByVal forceNew As Boolean, 
                    Optional ByVal ViewModel As VistaViewModel = Nothing)

So I tend to using the option #1 if the view does not need any extra parameter to create the viewModel and #3 otherwise (and the ViewModel must be passed to the Navigate function as a parameter)

Jonx
Jonx
08 Jun 2010

I prefer option 3. I like to see what is done and do it explicitly with code... Also, I still find it much easier to debug in case of problems...

Ken
Ken
08 Jun 2010

Nice summary. I've used all of them except for #6. These days I tend to use option 2, plus option 4 when appropriate.

Brad Leach
Brad Leach
08 Jun 2010

I use a combination of option 4 and option 6. I do this by using a MarkupExtension which is a service locator.

DataContext="{i:ServiceDependency Type={x:Type local:MyViewModel}}"

This way, the designer still works, but I get my VM hooked up with one simple line. I can also provide a specific DesignTime object by using the following:

DataContext="{i:ServiceDependency Type={x:Type local:MyViewModel}, DesignType={x:Type local:MyDesignViewModel}"

This also simplified my binding:

<TextBox Text="{Binding Path=...}" />
08 Jun 2010

Hey Paul,

I feel the need to fly the flag for #7, too - I believe it does have a valid use-case.

I would use this pattern if I wanted to show a collection of objects in a container, like a TabControl, and wanted to dynamically add/remove tabs at runtime.. by binding the ItemsSource of the ItemsControl to an ObservableCollection<VMBase> and ensuring your VM's inherit VMBase, you can provide DataTemplates for each VM - Bob's your uncle :)

Josh Smith does this in his MVVM sample app...

(Mostly I use 1-3, though)

Daniel Spruce
Daniel Spruce
08 Jun 2010

Hey Paul,

Can you explain a bit why #7 is no good? We're using it in a similar way it Ian, to bind content to a base class on dynamically swap the view implementation based on type.

08 Jun 2010

Daniel, Ian, Marek,

I think the pattern you've shown is different to what I had in mind for option 7. In my #7, the template would look like:

<DataTemplate DataType="...">
    <Grid>
        <TextBox Text="{Binding...} />
    </...>
</DataTemplate>

Where basically the entire view is declared in the template - that's what I meant by "don't use a real view at all".

The approach you've described is different, in that you still have a real view, you just use a data template to host it.

Option 8: Data Template and View

Similar to 7, this approach uses a data template to select the appropriate view for a given view model, but the view still has its own class.

<DataTemplate DataType="{x:Type ViewModels:CalculatorViewModel}">
    <Views:CalculatorView />
</DataTemplate>

I'm happy with this pattern - it's option 7 that's a little extreme for me (I happen to think code behind is a good thing used correctly - you lose that with option 7, but you keep it with option 8).

Alister
Alister
09 Jun 2010

I think i just cut myself....

The hardest part of MVVM for me was figuring out what to put where (being a xaml newbie too meant i struggled to know what i could do in xaml vs code behind vs view model). This started at "how do construct the View and ViewModel ?" So I think the post is really good - i'm adding my 2 cents.

I don't see a great difference between #7 and #8 either. I use #7, in conjunction with a custom control - so while losing the code behind capability there is still plenty of space for code in the control. Maybe i would use #8 if i wasn't using a custom control.

The datatemplates live in a resource dictionary. The resources in scope then determine which datatemplates are resolved. So we can have different "views" for the same viewmodel. Or you can explore datatemplate selectors if finer grained resolution is required. We used unity too (regions etc) - so at the top level view resolution is done by the container, but lower down it's done by data templates.

I'm not a guru at all - I think the combo and MVVM works - but there is a lot of hype for MVVM and few industrial strength examples that show true testability, mediators etc

Carl Scarlett
Carl Scarlett
09 Jun 2010

Great post Paul! It's nice to see these approaches summarised in one place.

I admit to being an occasional lunatic! As Ian says, there are times it is very appropriate. I know I've used it in the past simply as a XAML hiding excercise; simplifying the structure of the view by hiding the details as data templates in the resource section. It does feel wrong though, so I do avoid it.

I think a lot of the techniques you've listed have come about as techniques for organising our code due to inadequate tooling. Remember the days of the VS2008 designer not being able to render valid XAML? It feels like only yesterday! * grin *

Seriously though, as UI designers like Blend and VS2010 designers mature I envisage the techniques we employ may change a bit. However, until there's a new pattern that moves us away from MVC based patterns I can't see the first three options going away for quite some time.

My final comment on this; The fact that WPF/Silverlight are so flexible to allow so many ways to do one thing is one of it's greatest strengths. It may be hard to learn, but it's so damn -flexible-! How can you not love that!

09 Jun 2010

My final comment on this; The fact that WPF/Silverlight are so flexible to allow so many ways to do one thing is one of it's greatest strengths. It may be hard to learn, but it's so damn -flexible-! How can you not love that!

Absolutely :)

10 Jun 2010

7. I m not joking, and to honest I thought you were joking when you suggested it is not obviously the best option.

Like yourself, Paul, I have been knocking up these Compostie WPF apps for over 3 years now and there is only so much boiler plate guff that one can handle like:

public class MyView : IView { public MyView(....) //Inject it, created it what ever it is all silly to me. { InitialiseConmponent(); DataContext = .... } }

This code just does not need to live. It solves no problem and just creates busy work and more assets.

Further more I can easily test my Controller and viewmodel when these UserControl views are not involved. One less interface to worry about (register, add to tests, add as a chain of delegation).

I came to this conclusion by driving out several projects in a TDD manner, and it became obvious that UserControls were of no use to the project.

*Caveat: Some proects have "Blenders" in which case I would lean towards the #8 so they can see their pretty bits. Another case for UserControls is those Rare scenarios where a CodeBehind file is required to fulfil functionality that couldnt be done with DataTemplates.

my $0.02

Lee Campbell

13 Jun 2010

I've recently become a big fan of 5 and 6 purely because it can let you have some really succinct XAML inside data templates.

In regard to the syntax in your example code, are you sure you can have a DynamicResource as the Source for a DataBinding, I thought it was limited to StaticResource?

Great article!

Dave
Dave
13 Jun 2010

When I read this article I immediately said to myself "option #8 rules". Then i browsed through my code and found that I'm using other options also, depending on which is most convenient in a specific context. So I would not list one option, rather a top 3 most used:

  1. Option #8 (when one viewmodel has only one corresponding view)
  2. Option #8.1 (hey, i guess that's missing from your list): DataTemplateSelector.
  3. Option #3 (either DI plays a significant role or the project is distributed)
14 Jun 2010

I preffer option 9 - using MEF :):):) Probably you've missed to mention this approach ??

18 Jun 2010

I pass the viewmodel into the constructor and assign it to a property. Instead of having a normal variable/field backing the property I assign it to the DataContext. That allows the ViewModel property on the view to only accept the correctly typed viewmodel, and all calls from the view access the viewmodel via that property. Works really well.

ie:

ViewModel.DoSomeWork(); called from the view. The View only knows its viewmodel via that property and the viewmodel is oblivious of what views are using it.

not seen anyone else doing that (not sure if its a good idea either but its worked the last 3 years for me!) :)

cheers, Stephen

jbe
jbe
18 Jun 2010

An alternative approach is shown here: WPF Application Framework (WAF).

Sumit
Sumit
15 Jul 2010

Can anyone suggest which is the best approach for using UserControls and creating multiple instances of single view(one xaml file) ???

Any help would be greatly appreciated.

Regards