You may, or may not, have heard that the Microsoft Patterns and Practices team recently shipped the newest version of Prism.  With the latest 5.0 version of Prism comes A LOT of breaking changes, bug fixes, new features, and brand new functionality.  One of these brand new functional additions is a ViewModelLocator.  Now, I personally have never been a fan of ViewModelLocator for a number of reasons, but I must say, after playing around with it and having many conversations with my friend Brian Noyes, that I am really starting to like Prism’s version of ViewModelLocator.

One of the cool things the P&P team did was create a separate set of assemblies for everything MVVM for Prism.  This means that there is a new component of Prism, that exists completely separate of Prism.Composition.dll (formerly known as the Prism.dll) assembly.  basically, you can use all the MVVM goodies, such as BindableBase, DelegateCommand, CompositeCommand, and ViewModelLocator with absolutely zero dependencies on anything else related to Prism.  Since this post concentrates on just the ViewModelLocator, let’s just jump right into the code.

First you will want to create a new XAML application.  Since this New Prism.Mvvm component is a PCL, it doesn’t really matter what application type you create.  I will use a WPF application for my examples.  Next, go ahead an add a new Nuget reference, and search for Prism.Mvvm.  Once you find it, install it.

Prism.Mvvm nuget package

Once installed, you will notice three new references:

  • Microsoft.Practices.Prism.Mvvm – contains the bulk of the MVVM features such as BindableBase, DelegateCommand, CompositeCommand, ViewModelLocatorProvider
  • Microsoft.Practices.Prism.Mvvm.Desktop – contains a WPF specific attached property for using ViewModelLocator in a WPF application
  • Microsoft.Practices.Prism.SharedInterfaces – Contains IActiveAware which Prism.Mvvm is dependent upon.

Before we can really get into using the ViewModelLocator, we need to supply a simple View and ViewModel to use as an example.  First we need to create two folders in our project; one called Views which will contain our Views, and another called ViewModels which will contain our ViewModels.  We also need to create a View, which I am going to call MainDemo, and a ViewModel that I am going to call MainDemoViewModel.  I made sure I followed the ViewModelLocator convention and prefixed my ViewModel name with “MainDemo”, and added “ViewModel”, to make the complete name MainDemoViewModel.

IMPORTANT: Prism’s ViewModelLocator is convention based and requires that your Views, and ViewModels, be located in their respective Views and ViewModels folders.  Technically this is because when you create classes in these folders the namespace match the folder structure.  So this requirement really exists on the namespaces, meaning as long as your namespaces meet the convention, the actual folder structure can be anything you want.  Not only that, the ViewModel name must be prefixed with the corresponding Views name, plus “ViewModel”.  If you don’t, it won’t work!  I personally hate this convention, and I’ll show you how to change it later.

You should have something similar to this:

Folder setup

Here is our simple View:

<Window x:Class=”ViewModelLocatorDemo.Views.MainDemo”
       xmlns=”http://schemas.microsoft.com/winfx/2006/xaml/presentation”
       xmlns:x=”http://schemas.microsoft.com/winfx/2006/xaml”
       Title=”MainDemo” Height=”300″ Width=”300″>
    <Grid>
        <TextBlock Text=”{Binding Message} FontSize=”36″ />
    </Grid>
</Window>

Here is our simple ViewModel:

public class MainDemoViewModel : BindableBase
{
    string _message = “Hello World”;
    public string Message
    {
        get { return _message; }
        set { SetProperty<string>(ref _message, value); }
    }
}

Don’t forget to update your App.xaml StartUpUri to use our newly created View.

<Application x:Class=”ViewModelLocatorDemo.App”
            xmlns=”http://schemas.microsoft.com/winfx/2006/xaml/presentation”
            xmlns:x=”http://schemas.microsoft.com/winfx/2006/xaml”
            StartupUri=”Views/MainDemo.xaml”>
    <Application.Resources>
        
    </Application.Resources>
</Application>

Now that we have all the hard stuff out of the way.  We need to set the DataContext of the View to an instance of our ViewModel.  In order to do that, we will be using the ViewModelLocator.  Let’s makes some changes to our View.

<Window x:Class=”ViewModelLocatorDemo.Views.MainDemo”
       xmlns=”http://schemas.microsoft.com/winfx/2006/xaml/presentation”
       xmlns:x=”http://schemas.microsoft.com/winfx/2006/xaml”
       xmlns:prism=”clr-namespace:Microsoft.Practices.Prism.Mvvm;assembly=Microsoft.Practices.Prism.Mvvm.Desktop”
       prism:ViewModelLocator.AutoWireViewModel=”True”

As you can see, we added a namespace that contains the ViewModelLocator attached property which is located in the Microsoft.Practices.Prism.Mvvm.Desktop assembly.  Then we defined the ViewModelLocator.AutoWireViewModel attached property on our View and set the value to true.  If you try to run the application as is, it’s not going to work.  Why?  Well, because we need ot make a small change to our View’s code-behind.

public partial class MainDemo : Window, IView
    {
        public MainDemo()
        {
            InitializeComponent();
        }
    }

You will notice that we added an interface to our View called IView.  This interface is really easy to implement. Actually, it’s already implemented.  IView simply contains a property called DataContext which is of type Object.  Hey, what do you know, our View already has that property defined.  Great, we don’t need to do anything else.  Let’s run the app and see what happens.

image

YAY!  Success!  The ViewModelLocator magically created an instance of our ViewModel, and set it as the DataContext for our View.  Very nice!

Change those Nasty Conventions

If you are anything like me, I really hate putting my ViewModels in a folder called ViewModels!  This is actually one of my biggest no-no’s that I tell people not to do when creating large production applications using MVVM.  Why?  Because you are taking the class that contains all the state and business logic for a View and putting it somewhere in your app that is nowhere close to the actual View.  Come on guys!  It’s hard enough to find anything in the Visual Studio Solution Explorer as it is.  Now you want to place distance between files that are directly related to each other?  This seems to work when you first start writing an app, or for smaller apps, but think about your workflow when the applications get large.  Folders are expanded, tons of ViewModels are in one location, tons of Views are in another.  You have to jump around the Solution Explorer to find the right folders, and then scan those list of files in the folder to find related files is just a big pain in the butt.  I always place my ViewModels right next to my View.  Now there will be scenarios when this won’t make sense and you want to separate your ViewModels from your Views, but for the most part it doesn’t make sense.  Trust me, when your applications source code get to the point where it doesn’t all fit in the Solution Explorer without having to scroll, you will be thanking me.

So how exactly do you change these conventions?  It’s easy, but not at all obvious.  First let’s change up our structure from the “norm”.  Let’s drag our MainDemoViewModel, and place it in the same folder as the View.  We also want to remove the “ViewModels” name from the namespace of the MainDemoViewModel class, and add “Views” to place it in the same namespace as the MainDemo view.  So now you should have something like this:

image

Now if you try to run the application it won’t work, because we are not following the convention.  No problem, let’s just ass a little code to App.xaml.cs.

public partial class App : Application
{
    protected override void OnStartup(StartupEventArgs e)
    {
        base.OnStartup(e);

        ViewModelLocationProvider.SetDefaultViewTypeToViewModelTypeResolver((viewType) =>
        {
            var viewName = viewType.FullName;
            var viewAssemblyName = viewType.GetTypeInfo().Assembly.FullName;
            var viewModelName = String.Format(CultureInfo.InvariantCulture, “{0}ViewModel, {1}”, viewName, viewAssemblyName);
            return Type.GetType(viewModelName);
        });
    }
}

We can tell the ViewModelLocator how where to find the ViewModels by implementing the ViewModelLocatorProvider.SetDefaultViewTypeToViewModelTypeResolver that is located in the Microsoft.Practices.Prism.Mvvm assembly.  Now this method has a confusing name, and is poorly documented.  There is no way you would discover on your own what exactly this method should do or return.  This method gets called whenever a View is asking for a ViewModel.  Then, the ViewModelLocator takes the Type that is returned form this method, and uses it to instantiate an instance of that type, and then uses it as the DataContext of the View using the IView interface.  Simply put, this method is responsible for returning the Type of the ViewModel.  In the code snippet above, we are getting the Views name, and getting the Views namespace.  Next, we create the correct fully qualified name of the ViewModel.  Once we have that, we return a proper Type object using the newly generated ViewModel name.

Would you like DI with that?

The other cool thing I like about Prism’s implementation of ViewModelLocator, is that you can easily use a DI (dependency injection) container to resolve your ViewModels, and all of their dependencies.  Now, I’m not going to get into what DI is, or how it works, but I will share a quick code snippet on how to use one.  You just need to implement the ViewModelLocator.SetDefaultViewModelFactory method.

//example using Unity
IUnityContainer _container = new UnityContainer();

ViewModelLocationProvider.SetDefaultViewModelFactory((type) =>
    {
        return _container.Resolve(type);
    });

By default, this method uses Activator.CreateInstance, but as you can see, you can easily change it to use anything you want.

Well, that does it for this post.  I hope I gave you enough information to get you started with the new ViewModelLocator that is available in the Prism.Mvvm Nuget package.  Be sure to download the source code, and start playing around with it .  As always, feel free contact me on my blog, connect with me on Twitter (@brianlagunas), or leave a comment below for any questions or comments you may have.

Brian Lagunas

View all posts

24 comments

  • Brian,

    Great article. You provide those critical missing pieces related to the SetDefaultViewTypeToViewModelTypeResolver and the SetDefaultViewModelFactory.

    I did notice I was failing to compile on you call to GetTypeInfo() and had to change the code to below to work:

    ViewModelLocationProvider.SetDefaultViewTypeToViewModelTypeResolver((viewType) =>
    {
    var viewName = viewType.FullName;
    var viewAssemblyName = viewType.Assembly.FullName;
    var viewModelName = String.Format(CultureInfo.InvariantCulture, “{0}ViewModel, {1}”, viewName, viewAssemblyName);
    return Type.GetType(viewModelName);
    });

    Much appreciate your leadership and guidance in the Prism space with Infragistics. We’re also users of the TabGroupPaneRegionAdapter.

    Thanks again,
    Damon Carr, Senior WPF Developer
    PIMCO

    • I am glad you found value in the post. Your kind words encourages me to continue my efforts in sharing my knowledge. As for your compilation issue; you probably forgot to add the “using System.Reflection;” to get the GetTypeInfo extension method. Let me know if you have any other issues or questions.

  • Hi Brian,

    Need a proofreader? How about for this sentence above: “No problem, let’s just ass a little code”

    Don’t get me wrong, I love it. But you probably meant “add”.

    -reilly.

    • Yeah, I noticed that a week or so ago, but I was too lazy to fix it. Thanks for reminding me. I’ll get around to updating eventually :0)

  • Curious as to the how to decide between using SetProperty versus just SetProperty?

      • Hi,

        I just came across this article. It’s really good, thank you! But I have a question:
        Is there any advantage to use that standard property setter syntax? Or what is the reason for it?

        • Using the SetProperty just does an equality check of the current value and the new value. If they are the same, it sets the property to the new value and then calls OnPropertyChanged. If they are not the same, nothing happens.

  • Hi,
    Congrats, very useful post. I’ve been wondering how to use DI with the ViewModelLocator the whole week, the last paragraph is like gold for me.
    Thanks

  • when i tried to use it with a view model that depends on IRegionManager it doesn’t fire constructor of the view model

  • sorry for confiusion it runs the constructor but i have a navigation in the constructor but it doesn’t navigate also the code is executed

    • I’m sorry but there isn’t enough information in your question to help identify the issue you are having or what the cause may be. I think we can safely say it’s not an issue with the ViewModelLocator.

  • Hi Brian, i like that implementation. I´ve been looking for simple viewmodellocator, and this seems pretty simple. But how to you navigate? Normally i would set the view in my mainviewmodel as a property, and bind the content of the frame to that property – swithing view like this :

    property in viewmodellocator:
    public Page Selected page {get;set;}

    then navigate like this

    SomeCommand = new RelayCommand(()=> ViewModelLocator.SelectedView = new SomeView())

    and set the context of whatever viewmodel that belongs to that view in the xaml.

    Cheers, hope i made sense.

    • For one, never create view objects in your Viewmodels. In order to achieve loosely coupled navigation in MVVM with WPF, you can use the Prism navigation framework. What platform are you using?

      • I´m using WPF. I know having viewlogic in viewmodels kinda breaks the pattern, but i find navigating in MVVM difficult ..

  • Hi Brian,

    I test with Prism for Xamarin.

    prism:ViewModelLocator.AutoWireViewModel=”True”

    Doesn’t work for ContentView.

    • Works for me! There has been a change in the ViewModelLocator convention. If you are naming your ContentView something like MyContentView, you need to name the ViewModel MyContentViewModel. It cannot be named MyContentViewViewModel.

  • Small question, by using the ViewModelLocator in the XAML and implementing the IView in the code behind, you should still have the warning in the XAML saying that the View should implements IView, how did you handle this?

    • Sorry for the late reply, I haven’t been getting notifications of new comments for some reason. This is no longer an issue with Prism 6. Actually in Prism 6, IView has been removed.

  • Hi Brian,

    I have found all of your posts and videos on your blog, Infragistics and Channel 9 to be very valuable, as a hobbyist. There’s one thing I’ve been trying to find, and it may be my google-foo is just terrible. Likewise, I may just be approaching my problem in the wrong way.

    I’ll summarize the question here, and provide the context below. What is the best way to not only add your ViewModel to your View’s DataContext, but also feed that ViewModel with data from a Parent ViewModel? I have no clue if that was the right way to describe that.

    I have a Main Window with it’s own ViewModel (and it’s Model which I load or unload whenever). The View contains a TabControl with approximately 20 TabItems. Each Tab then contains an Itemlist of a different type of Object (from the Model mentioned previously) and 3 buttons which I intend to connect to DelegateCommands (i.e. New, Edit, Delete), which need to make decisions based on the ItemList’s SelectedItem.

    This being the case, I assume I need to set the DataContext for each TabItem to its own ViewModel. I have no problem with that, though my ultimate question is, how do I define the ViewModel, while also providing it the data from my Model? I can only set the DataContext on the View with one or the other. The challenge is I can load the top level Model or Unload it at anytime, so when I open a new Model, I need all of the TabItems to update based on Lists in the Parent Model.

    Does this really come down to just using long-hand code during the initial constructor of the MainWindowViewModel and/or the Model’s Setter? Right now I am accessing most of my Model datal (Object Lists) directly using binding; should I instead add them to their own ViewModels which I expose as properties in the top ViewModel and then bind that down to the tabs?

    Obviously I ended up on this article thinking the ViewModelLocator was the answer to my problems, but I’m just not seeing it.

    Am I just over thinking things with this? Am I missing something extremely simple by trying to force MVVM down my own throat? Any thoughts on good articles, books or video series I should be investing my time into regarding something like this? I appreciate all of the insight you’ve provided the community in regards to MVVM.

    • Sorry for the late reply, I haven’t been getting notifications of new comments for some reason. Wow, that’s a lot to take in. First off, there are many ways to accomplish what you want. It is really hard to guide you in the right direction without knowing more about how your app is architected. If all 20 tabs are related to the same mode, and is just showing child data, or metadata about a single model, then why give those tab items different ViewModels? Seems like that can all share the same DataContext (which will automatically be inherited). SO I actually see the need for one ViewModel. For your New, Edit, Delete, buttons, just use interfaces and polymorphism to encapsulate all your logic into only three commands for all the new, edit, delete commands.

Follow Me

Follow me on Twitter, subscribe to my YouTube channel, and watch me stream live on Twitch.