Geeks With Blogs

News Locations of visitors to this page
Brian Genisio's House of Bilz

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.

Posted on Friday, June 4, 2010 3:17 PM | Back to top


Comments on this post: Adventures in MVVM – ViewModel Location and Creation

# re: Adventures in MVVM – ViewModel Location and Creation
Requesting Gravatar...
Hey Brian,

I will have something like this in MVVM Light V4, because I too am not satisfied with the current state of the ViewModelLocator in MVVM Light.

I like the generic VML with a configuration class which is customizable. I have also played with this and it is my favorite solution at the moment. Bottom line is, one cannot push MEF or any other location technology on the end user (as much as I like MEF) but it is necessary to provide a lightweight, no-dependency solution. In fact i am thinking of providing a super light service locator class in MVVM Light V4 that can also be used in other scenarios (such as locating dialog services, etc).

Right now, the only challenge i see is to make the syntax is Silverlight friendlier. I am thinking along the lines of a generic converter maybe... Not sure yet.

Anyway, thanks for the post and the shout out :)

Laurent
Left by Laurent Bugnion on Jun 04, 2010 6:07 PM

# ViewModel Location and Creation
Requesting Gravatar...
Hey Brian,

It seems that your "View Model Location and Creation" solution is nor fully bendable :

The Good : Binded datas are displayed in the artboard

The Bad : Whereas DataContext property is well set, binded view model's properties does not appear in the "DataContext" pane (located in the "Data Window", near resources and Properties). Furthermore, when you try to bind with the help of the "Data Binding...." Dialog box, the DataContext pane is only filled with "ViewModelLocator -> Resolver".

(Blend 4 RC used for tests)

Compared with "Laurent Bugnion" approach, it's a big miss !

Note ! the "MEFedMVVM" approach (Marlon Grech) have the same problem....

Blendability is very important for me : It lets designers easily drag&drop DataContext's properties and Commands on UI Elements displayed in the artboard.

Do you have any solution to solve this problem ?

Fred
Left by Frederic POINDRON on Jun 06, 2010 7:20 PM

# re: Adventures in MVVM – ViewModel Location and Creation
Requesting Gravatar...
Fred,

Yeah, I forgot to talk about that. For me, it doesn't get in my way much. My workflow with my designer is such that I build up the behavior in my ViewModel and I bind a very simple UI to it. At that time, I hand it off to my designer and he goes nuts with it to make it look pretty... but he rarely needs to worry about doing the binding because I have already done it for him.

That said, I am certainly NOT discounting your concern.

The solution for this was pointed out in John Papa's article... it requires a little directive to tell Blend what the data type is. I don't love this solution, but here is what you need to add (change the type to your type):

d:DataContext="{d:DesignInstance Type=local:CanExecuteViewModel, IsDesignTimeCreatable=True}"

When you do this, it solves the problems you talk about and you are on your way.

Brian
Left by Brian Genisio on Jun 07, 2010 12:36 AM

# re: Adventures in MVVM – ViewModel Location and Creation
Requesting Gravatar...
Good Job Brian !

It works. Thanks a lot !
Left by Frederic POINDRON on Jun 07, 2010 1:09 AM

# re: Adventures in MVVM – ViewModel Location and Creation
Requesting Gravatar...
Hi Brian, thanks a lot for the very interesting posts! I'd like to know your opinion about the situations where ViewModel needs to receive external parameter (for instance, in order to pass this parameter to the Model to get data from web service, etc.)... How that type of the task can be accomplished while using your ViewModel Location implementation?

Eugene
Left by Eugene on Jun 08, 2010 4:24 PM

# re: Adventures in MVVM – ViewModel Location and Creation
Requesting Gravatar...
can u please give me syntax of ViewModelLocator
Left by Shruti on Aug 21, 2012 7:30 PM

Your comment:
 (will show your gravatar)


Copyright © Brian Genisio's House Of Bilz | Powered by: GeeksWithBlogs.net