Adventures in MVVM – ViewModel Location and Creation

More Adventures in MVVM Shout it

In this post, I am going to explore how I prefer to attach ViewModels to my Views.  I have published the code to my ViewModelSupport project on CodePlex in case you’d like to see how it works along with some examples.

Some History

My approach to View-First ViewModel creation has evolved over time.  I have constructed ViewModels in code-behind.  I have instantiated ViewModels in the resources sectoin of the view. I have used Prism to resolve ViewModels via Dependency Injection. I have created attached properties that use Dependency Injection containers underneath.  Of all these approaches, I continue to find issues either in composability, blendability or maintainability.

Laurent Bugnion came up with a pretty good approach in MVVM Light Toolkit with his ViewModelLocator, but as John Papa points out, it has maintenance issues.  John paired up with Glen Block to make the ViewModelLocator more generic by using MEF to compose ViewModels.  It is a great approach, but I don’t like baking in specific resolution technologies into the ViewModelSupport project.

I bring these people up, not to name drop, but to give them credit for the place I finally landed in my journey to resolve ViewModels.  I have come up with my own version of the ViewModelLocator that is both generic and container agnostic.  The solution is blendable, configurable and simple to use.  Use any resolution mechanism you want: MEF, Unity, Ninject, Activator.Create, Lookup Tables, new, whatever.

How to use the locator

1. Create a class to contain your resolution configuration:

public class YourViewModelResolver: IViewModelResolver
{
    private YourFavoriteContainer container = new YourFavoriteContainer(); 

    public YourViewModelResolver()
    {
        // Configure your container
    } 

    public object Resolve(string viewModelName)
    {
        return container.Resolve(viewModelName);
    }
} 

Examples of doing this are on CodePlex for MEF, Unity and Activator.CreateInstance.

2. Create your ViewModelLocator with your custom resolver in App.xaml:

<VMS:ViewModelLocator x:Key="ViewModelLocator">
    <VMS:ViewModelLocator.Resolver>
        <local:YourViewModelResolver />
    </VMS:ViewModelLocator.Resolver>
</VMS:ViewModelLocator> 

3. Hook up your data context whenever you want a ViewModel (WPF):

<Border DataContext="{Binding YourViewModelName, Source={StaticResource ViewModelLocator}}"> 

This example uses dynamic properties on the ViewModelLocator and passes the name to your resolver to figure out how to compose it.

4. What about Silverlight?

Good question.  You can’t bind to dynamic properties in Silverlight 4 (crossing my fingers for Silverlight 5), but you CAN use string indexing:

<Border DataContext="{Binding [YourViewModelName], Source={StaticResource ViewModelLocator}}"> 

But, as John Papa points out in his article, there is a silly bug in Silverlight 4 (as of this writing) that will call into the indexer 6 times when it binds.  While this is little more than a nuisance when getting most properties, it can be much more of an issue when you are resolving ViewModels six times.  If this gets in your way, the solution (as pointed out by John), is to use an IndexConverter (instantiated in App.xaml and also included in the project):

<Border DataContext="{Binding Source={StaticResource ViewModelLocator},
    Converter={StaticResource IndexConverter}, ConverterParameter=YourViewModelName}">

It is a bit uglier than the WPF version (this method will also work in WPF if you prefer), but it is still not all that bad.

Conclusion

This approach works really well (I suppose I am a bit biased).  It allows for composability from any mechanisim you choose.  It is blendable (consider serving up different objects in Design Mode if you wish… or different constructors… whatever makes sense to you).  It works in Cider.  It is configurable.  It is flexible.  It is the best way I have found to manage View-First ViewModel hookups.  Thanks to the guys mentioned in this article for getting me to something I love using.  Enjoy.

Tags: ,

5 Responses to “Adventures in MVVM – ViewModel Location and Creation”

  1. Stuart says:

    Hi

    I’ve just tried to apply your code to both my existing project and (to check) a brand new SL project and the problem I’m finding is that in each case the viewmodel is being called half a dozen times. So of course to test further I set a breakpoint in your code – the constructor in DependentPropertiesViewModel in ViewModelExamples_SL – and I notice it happens there too! Have you any idea why? Surely this is a mistake?

    Otherwise very interesting.

    Thanks

  2. admin says:

    @Stuart:

    If you are using the [string] indexer syntax in Silverlight, there is a bug that causes the binding to string indexing to happen six times. The fix is to use the IndexConverter outlined in this article.

    This should not happen in WPF at all… and you don’t need to use the string indexer syntax either… it uses Dynamic to resolve it.

    Brian

  3. Andrew says:

    Brian,

    I’m trying to implement your solution in SilverLight 4, but I’m getting an error in my app.xaml:

    Error 31 The tag ‘ViewModelLocator’ does not exist in XML namespace ‘clr-namespace:ViewModelSupport_SL;assembly=ViewModelSupport_SL’.

    I have a reference to the ViewModelSupport_SL assembly in my SilverLight project and I can reference the ViewModelLocator in the codebehind.

    Here is my app.xaml:

    What is weird is if I don’t code up the app.xaml and use this codebehind, it works at run-time but not at design-time:

    private void Application_Startup(object sender, StartupEventArgs e)
    {
    ViewModelLocator vml = new ViewModelLocator();
    vml.Resolver = new MyViewModelResolver();
    this.Resources.Add(“ViewModelLocator”, vml);
    this.Resources.Add(“IndexConverter”, new IndexConverter());
    }

    I love everything about your solution, except I cannot get the Blendability working. I appreciate any help you can provide.

    Andrew

  4. aqua17 says:

    can u please give me syntax of ViewModelLocator

Leave a Reply