Wiring up View and Viewmodel in MVVM and Silverlight 4 – Blendability included

Wiring up View and Viewmodel in MVVM and Silverlight 4 – Blendability included

Im a BIG fan of  Silverlight and also i really like the Model View ViewModel pattern. Nice part is that those two fit perfectly. The downside is that everyone is doing MVVM the way they like it or the way they think they like it. There is no strict guidance,  there are no ‘Bible’ kind of books written on the subject, there is only a enormous pile of information (of varying quality) on the web contributed by developers all over the world trying to (ab)use this pattern in their everyday practice.

(probably you can take this post as just another small contribution to that information pile on the MVVM).

Yes, there are many mature MVVM frameworks for Silverlight and WPF out there (Prism, MVVMLight, Caliburn etc) and they try to provide standardized ways of doing things but they either lack features or they are overly complex for my taste. Also problem with frameworks is that each of them solves some problems in good or excellent way yet other things are not covered or they are done in way that is not acceptable for each need.

So i guess if you could just merge them all to one solid framework it would be a hell of a tool.

One of the features that most of Silverlight MVVM frameworks are actively trying to solve is the process of wiring up Views and Viewmodels and related to this problem is so-called Blendability.  Blendability is just a fancy word for enabling designers to see the correct preview of their Views in Visual Studio and/or Expression Blend.

And this is not easy task that’s for sure.  Here is why:

As soon as your View Models become more complex and if you start using Dependency Injection with Constructor Injection – because IDE is trying to instantiate your ViewModel in designtime and fails – design surface will blow up in your face and instead of the preview you will just see some error message (if you are lucky enough and your IDE did not crashed already).

I do like how MVVMLight framework is preserving Blendability by using concept of the ViewModelLocator.

Basically this class is some sort of ViewModel factory that returns different ViewModel if its called in runtime or designtime. This keeps the IDE happy and it does not crash because it gets some dummy model when in designtime and when application is trully running it then gets realt ViewModel so everyone is happy 🙂

While this is pretty smart concept, i don’t like how it is implemented in practice.

In MVVMLight ViewModelLocator  is usaully defined in App.Xaml.cs as global resource (and therefore created on application startup).

Also designtime and runtime versions of ViewModel instances in ViewModelClass are defined as static properties and therefore also created when ViewModelLocator class is first used. Also those static ViewModels are then shared between multiple views which is in my opinion simply  wrong.

Every view should have its own ViewModel instance created for it in runtime.

For example what if i want to show same view multiple times on a single page? (lets say its case of multiple RSS feed widgets on one page each of them showing different RSS feed etc).

Each ViewModel should be instantiated at the same time as its View or at least i should have the freedom to choose when its created depending on the situation and also i should be able to choose if it is shared between multiple instances of same view or not.

So inspired by the concept of ViewModelLocator from MVVMLight i created my own variation of this class and i will be presenting this solution in this post.

So enough talk  lets first show some code. This is my current version of the ViewModelLocatorBase class:

ViewModelLocatorBase.cs:

using System.ComponentModel;
using Framework.Abstractions.Silverlight.ServiceLocation;

namespace Framework.Implementors.Silverlight.MVVM
{
  public abstract class ViewModelLocatorBase<TViewModel> : NotifyPropertyChangedEnabledBase where TViewModel : class
  {
    private static bool? isInDesignMode;
    private TViewModel runtimeViewModel;
    private TViewModel designtimeViewModel;

    /// <summary>
    /// Gets a value indicating whether the control is in design mode
    /// (running in Blend or Visual Studio).
    /// </summary>
    public static bool IsInDesignMode
    {
      get
      {
        if (!isInDesignMode.HasValue)
        {
          isInDesignMode = DesignerProperties.IsInDesignTool;
        }

        return isInDesignMode.Value;
      }
    }

    /// <summary>
    /// Holds the intance of the runtime version of the ViewModel that is instantiated only when application is really running by retrieving the instance from IOC container
    /// </summary>
    protected TViewModel RuntimeViewModel
    {
      get
      {
        if (this.runtimeViewModel == null)
        {
          this.RuntimeViewModel = SimpleServiceLocator.Instance.Get<TViewModel>();
        }
        return runtimeViewModel;
      }

      set
      {
        runtimeViewModel = value;
        this.OnPropertyChanged("ViewModel");
      }
    }

    /// <summary>
    /// Gets current ViewModel instance so if we are in designer its <see cref="DesigntimeViewModel"/> and if its runtime then its <see cref="RuntimeViewModel"/>.
    /// </summary>
    public TViewModel ViewModel
    {
      get
      {
        return IsInDesignMode ? this.DesigntimeViewModel : this.RuntimeViewModel;
      }
    }

    /// <summary>
    /// Holds the intance of the designtime version of the ViewModel that is instantiated only when application is opened in IDE designer (VisualStudio, Blend etc).
    /// </summary>
    public TViewModel DesigntimeViewModel
    {
      get
      {
        return designtimeViewModel;
      }

      set
      {
        designtimeViewModel = value;
        this.OnPropertyChanged("ViewModel");
      }
    }
  }
}

As you can see ViewModelLocatorBase is generic and abstract class that should be inherited by concrete ViewModelLocators, usually one for each View but this is not necessarily the case and you can have as many ViewModel locators for single view as you like (or you can share same ViewModelLocator between multiple instances of same View on one page if that is really what you need, also each view can have its own if needed).

Generic type TViewModel is usually the interface that your ViewModel is implementing (you could use concrete class type there but i strongly disagree with that – Views should bind to interfaces and later you can easily mock them etc).
ViewModelLocatorBase inside its static property IsInDesignMode determines if its instantiated inside aome IDE designer or inside the real running application.

I have tested it in Blend 3 and Visual Studio 2010 Beta 2 and it works fine.

Based on that fact (runtime or designtime) ViewModelLocatorBase.ViewModel property returns appropriate ViewModel instance.
If its designtime it returns value of DesignTimeViewModel property and if its runtime it returns RuntimeViewModel property value.
Now as you can see in the getter of RuntimeViewModel property, when its first time accessed it retrieves the concrete instance of our generic TViewModel type (it uses my home grown IOC adapter called SimpleServiceLocator but you can plugin any IOC you want behind it).

This instance is then saved to private property so its created only once.

So this way on runtime you will get there whichever concrete implementation you set up in your IOC for the TViewModel type.

Here is how i setup IOC in Bootstrapper class:

  public class Bootstrapper
  {
    public static void InitializeIoc()
    {
      SimpleServiceLocator.SetServiceLocatorProvider(new UnityServiceLocator());
      SimpleServiceLocator.Instance.Register<IMessageBoxService, MessageBoxService>();
      SimpleServiceLocator.Instance.Register<IEditUsersViewModel, EditUsersViewModel>();
    }
  }

To have something returned from the getter of the ViewModel in designtime we need to set the DesigntimeViewModel property.
We do that in the concrete ViewModelLocator class that is inheriting from ViewModelLocatorBase so that in design time IDE will get this instance.

Here is one simple concrete ViewModelLocator implementation:

  public class EditUsersViewModelLocator : ViewModelLocatorBase<IEditUsersViewModel>
  {
    public EditUsersViewModelLocator()
    {
      this.DesigntimeViewModel = new DummyEditUsersViewModel();
    }
  }

So the concrete EditUsersViewModelLocator class simply inherits the ViewModelLocatorBase and for the generic type it specifies the interface IEditUsersViewModel that ViewModels for the EditUsersView should implement and after this it sets the value of the DesigntimeViewModel property to a instance of DummyEditUsersViewModel which is a (as its name clearly states) just some dummy implementation of the IEditUsersViewModel with some test data to be displayed on the screen when editing this view in Blend or VisualStudio designer.

Sounds simple? well that was the original goal 🙂

Lets paste some more code. This is how the IEditUsersViewModel interface looks like:

  public interface IEditUsersViewModel
  {
    ObservableCollection<User> Users { get; }
    ICommand DeleteUserCommand { get; }
  }

Here is the dummy ViewModel for the design time that has test data to be displayed in designtime:
(it uses static properties to prevent VS2010 with r# from crashing if you open the views without first compiling the whole solution)

  public class DummyEditUsersViewModel : ViewModel, IEditUsersViewModel
  {
    private static ObservableCollection<User> users = new ObservableCollection<User>();

    static DummyEditUsersViewModel()
    {
      users = new ObservableCollection<User>
                     {
                       new User {Username = "Designtime User a", IsAdmin = true},
                       new User {Username = "Designtime User b", IsAdmin = true},
                       new User {Username = "Designtime Admin User c", IsAdmin = true},
                       new User {Username = "Designtime Admin User d", IsAdmin = true}
                     };
       deleteUserCommand = new DelegateCommand<object>(p => {});
    }

      private static ICommand deleteUserCommand;
      public ICommand DeleteUserCommand
      {
          get { return deleteUserCommand; }
          private set { deleteUserCommand = value; }
      }

      public ObservableCollection<User> Users
    {
      get { return users; }
      set { users = value;}
    }
  }

And here is how we would use this concrete ViewModelLocator in our view:

<UserControl x:Class="MvvmBlendability.Views.EditUsersView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:ViewModels="clr-namespace:MvvmBlendability.ViewModels" mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="400"  d:DataContext="{Binding Source={StaticResource viewModelLocator}, Path=ViewModel}"  >
    <UserControl.Resources>
        <ViewModels:EditUsersViewModelLocator x:Key="viewModelLocator"  />
    </UserControl.Resources>

    <UserControl.DataContext>
        <Binding Source="{StaticResource viewModelLocator}" Path="ViewModel" />
    </UserControl.DataContext>

    <Grid x:Name="LayoutRoot" Background="Silver" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="10">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"></RowDefinition>

            <RowDefinition Height="*"></RowDefinition>
        </Grid.RowDefinitions>
        <TextBlock HorizontalAlignment="Right" Text="Edit Users"  FontSize="18" Margin="0,10,10,5" FontFamily="Arial Black" />
        <ListBox Grid.Row="1" ItemsSource="{Binding Path=Users}" Background="AliceBlue" HorizontalAlignment="Stretch" >

            <ListBox.ItemTemplate>
                <DataTemplate>
                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition MinWidth="300"></ColumnDefinition>
                            <ColumnDefinition Width="21*"></ColumnDefinition>
                            <ColumnDefinition Width="21*"></ColumnDefinition>
                        </Grid.ColumnDefinitions>
                        <TextBlock Text="{Binding Path=Username}" />
                        <Button Grid.Column="2" Content="Del" Command="{Binding Source={StaticResource viewModelLocator}, Path=ViewModel.DeleteUserCommand}" CommandParameter="{Binding}" />

                    </Grid>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
    </Grid>

</UserControl>

In the Xaml its very important that you notice this part of the code in the UserControl definition:

d:DataContext="{Binding Source={StaticResource viewModelLocator}, Path=ViewModel}"

Its the very important part and if you miss this out you will not see much in the designer. This actually tells the designer what to use as DataContext of the UserControl (this is our view) in designtime and we will point it to the ViewModel property of our ViewModelLocator instance we defined in the UserControl.Resources section on top of the view.

Yet this code sets the DataContext binding for view for runtime:

    <UserControl.Resources>
        <ViewModels:EditUsersViewModelLocator x:Key="viewModelLocator"  />
    </UserControl.Resources>

    <UserControl.DataContext>
        <Binding Source="{StaticResource viewModelLocator}" Path="ViewModel" />
    </UserControl.DataContext>

We first create instance of out ViewModelLocator in resources of the UserControl (View) and then we set this as DataContext.
And in the design time in VisualStudio when we open EditUsersView we will get this:

As you can see design surface is working and we can see our View showing data from our  DummyEditUsersViewModel.

I have created one more View called ShellView and placed in its Xaml two instances of EditUsersView so that we can be sure it will work in this scenario also.

As i mentioned each instance of the view will get its own ViewModel created and wired up (in this case since its designtime each view will get its own instance of designtime view mode – DummyEditUsersViewModel).

First lets look at the xaml of the ShellView:

<UserControl x:Class="MvvmBlendability.Views.ShellView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:Views="clr-namespace:MvvmBlendability.Views" mc:Ignorable="d"
    d:DesignHeight="400" d:DesignWidth="400">

    <Grid x:Name="LayoutRoot" Background="White">
        <Grid.RowDefinitions>
            <RowDefinition></RowDefinition>
            <RowDefinition></RowDefinition>
        </Grid.RowDefinitions>
        <Views:EditUsersView Grid.Row="0" />
        <Views:EditUsersView Grid.Row="1" />
    </Grid>
</UserControl>

In the ShellView we have two instances of the EditUsersView and both of  them will be assigned with separate ViewModel instance as we declared it in the Xaml of those views via ViewModelLocator so we dont need any ViewModelLocator for ShellView.

Basically EditUsersViews are here used as a component that we dropped on another view and this component takes care of its own DataContext without having to worry about it again. Off course we could also create view that does not have ViewModel assigned via ViewModel locator and place it on ShellView and set its DataContext directly via DataBinding.

All possibilities  are there we just need to choose the appropriate one.

So lets see how ShellView looks in the VS2010 Beta 2 designer:

And its working in Blend also (but be sure to use Microsoft Expression Blend Preview for .NET 4 version to be able to open this solution. Its not working in plain Blend 3 because this version is not supporting VS 2010 projects/solutions).

So here is the ShellView in Blend:

On the other hand, when we actually run our application in browser then ViewModelLocator sets ViewModel property to the real ViewModel instance (runtime version) and view is populated with real data from EditUsersViewModel just as we would expect:
Here is how it looks when we start our application in the browser:

As you can see each instance of the View has different data shown that proves that each has different instance of ViewModel set to its DataContext.

So we have accomplished our three main design goals:

  1. Simple yet powerful View to ViewModel wireup
  2. Blendability
  3. simplicity 🙂

Im attaching the VisualStudio 2010 solution with full source code of project used in this post.
You can see the live demo of this app here.

Hopefully this has given you some ideas on how to start with MVVM without having to learn frameworks before you event start programming. Later when you realize that you cannot accomplish all your ideas you can always switch to some framework and use it.

Unitl then: Happy DataBinding!

33 thoughts on “Wiring up View and Viewmodel in MVVM and Silverlight 4 – Blendability included

  1. Pingback: DotNetShoutout
  2. Very nice implementation. In the dozen or so suggested patterns, I like this the best so far. The aha moment for me was this “d:DataContext” to support Blend. Clever!

    1. Thanks, i’m glad you find this interesting.
      Im on constant search for the best way to implement MVVM with Silverlight.
      I have some more interesting stuff to share regarding this so stay tuned 🙂

  3. Hi,

    Interesting take on the ViewModelLocator. For the records, I am not currently satisfied with the way it is in the MVVM Light Toolkit, and this is one of the things I will change in a further version. Since I am doing a framework, the two drivers for me are: It must work in SL3 and SL4, as well as WPF3.5 and WPF4 (so d:DataContext might not work properly in VS2008, I need to test that), and also I cannot use an IoC container (like Unity), because I cannot force an external dependency on my users. However I want to make it so the locator is easy to modify, should they want to add an IoC container of their choice.

    That said, I do not quite understand why you need d:DataContext. The binding you set to the Locator.ViewModel in your XAML code will actually be executed by Blend and the Visual Studio designer. So effectively what you do here is set the DataContext twice. Unless I missed something, you can remove the line with d:DataContext from your code and this will still work fine in Blend and VS designer.

    d:DataContext is useful when you want to set a different object in your XAML than in code behind. Also, if I may suggest, I think that you should rather look into d:DesignInstance, which is more advanced than d:DataContext. I personally see more promise in d:DesignInstance.

    If you think I missed something about the way you use d:DataContext, please let me know.

    Cheers,
    Laurent (from MVVM Light Toolkit)

    1. Hi Laurent,

      first of all thank you for your comments, and also for the inspiration since i used your ViewModelLocator from MVVM Light Toolkit as my starting point for my post.

      Now to answer to your questions:
      1. IOC – i don’t see why not to use it, why not be opinionated about things. I think IOC is very important for doing MVVM properly (or any other complex application) so why not enforce it.
      But off course give users a option to choose the IOC container and plug in a different one instead the default provided by tookit. Unity is very nice for Silverlight i highly recommend it.

      2. regarding the d:DataContext yes i would like to remove it but if i do i lose design time experience – so called Blendability.
      No idea why because my version of the ViewModelLocator is returning the DummyEditUsersViewModel for property ViewModel when called in design time.

      But it simply does not work. I tried everything and setting d:DesignContext (or d:DesignInstance) was only solution i could find.

      I think that VS 2010 designer actually queries this property ViewModel earlier then i set the DesigntimeViewModel in the constructor of my inherited ViewModelLocator and for that reason it gets null so that’s is why it fails (i simply set the DesigntimeViewModel too late).
      If you have any solution for this i would be glad to hear.

      cheers,
      Slobo

      1. Hi,

        About IoC: I think it should be used where needed. Don’t get me wrong, I like IoC and I see the utility of it. That said, there are many ways to do IoC, even just in the choice of the framework (I tend to favor MEF, but Unity, StructureMap, NInject etc all have some good sides). Second, when you create a framework, I think you shouldn’t enforce anything. I worked for clients where additional libraries where forbidden. My goal is to educate people and let them understand why things are good for them, but sometimes the client’s reason is actually correct. For example, for a Silverlight application, size matters, so adding a 200+KB DLL in the XAP is a big no-no for some clients. It all depends on the scenario!

        About DataContext: The d:DataContext should not be needed with the locator. StaticResource is instantiated at the time of parsing, so the ViewModelLocator will get created before the binding on the DataContext property is set.

        I made you a small sample where you can see that d:DataContext is not needed. It uses an IMainViewModel interface, and defines a MainViewModel (runtime) and a DesignMainViewModel (design time).

        Note that nowadays however I tend to not use design time ViewModel anymore (except for small apps) and instead have services to handle data. It is easier to have a design time service and runtime service, the objects are smaller and can be tested in isolation. But the principle is exactly the same: The ViewModelLocator detects if it is running in design mode or not, and select the appropriate services. This is where it is easy to add an IoC container if desired.

        Where can I send you the sample?
        Cheers,
        Laurent

        1. Im interested to see the solution you prepared please do send it to webmaster [ aT ] roboblob.com.
          But keep in mind that i dont want to make my ViewModelLocator (or its inheritor) to be static or to have static properties for ViewModels.
          I want to instantiate the ViewModels at the same time when View is created (by default off course, this can vary in some situations)

          regarding the IOC if you don’t want to ship your toolkit with third party IOC why not implementing custom simple one just to provide this feature and then user can plug in different 3rd party IOC if he wants?

          Thanks!

  4. I found this article helpful, I’m trying to overcome similar designer issues with our solution, while also being fairly green to Silverlight.

    I tried to implement your example in our project, but I got stuck with our use of Modularity and the bootstrapper not having a reference to the project that contains the view/viewmodels for the module.

    If you had time and wouldn’t mind dropping me an email, maybe you wouldn’t mind nudging me in the right direction?

    Thanks

    Kathleen

    1. Yes off course,
      send your questions directly to webmaster [aT] roboblob.com i will be glad to help if i can.
      If you have concrete problem send me archive with full source code so i can take a look.

  5. Why not put the design/runtime separation in the ViewModel constructor and call it day. Why do you need the Locator? Love the whole concept though of the d:DataContext. Fantastic!!

    class ExampleViewModel : ViewModel
    {
    public ExampleViewModel()
    {
    if (InDesignMode)
    {
    // Load fake data
    // Wireup fake Commands
    }
    else
    {
    // Load real data
    // Wireup real Commands
    }
    }
    }

    1. Yes i went down the path of InDesignMode and it is an valid option. Recently i have abandoned ViewModelLocator concept it became too clumsy.
      Now i use IVIewNavigationService that loads Views and automatically wires them up with their ViewModels and supports animations etc.
      I will blog about this soon, its something I’m still working on.

      I’m glad you found the d:DataContext useful, i find it to be lifesaver also.

      Thanks for the feedback!

      1. Hey Rob,
        I have been struggling with the clumsiness of the ViewModelLocator as well, and have been searching for a more elegant concept. Can you tell me more about the navigation service concept? I’m very interested in new ideas to the challenge of wiring up and instantiation of view models.

        Thanks!
        Sam

        1. Hi Sam,
          yes ViewModelLocator definitely has its problems.
          I have completely abandoned that approach and have a working stable implementation of small MVVM framework that uses IViewNavigationService that you can call and just pass a name of the View, or a ViewModel type and it automatically finds appropriate View/ViewModel, wires them up and then shows on screen.
          It works with little bit extended Silverlight NavigationFramework.
          Problem is that i cannot find time these days to put together nice blog post about this.
          Hopefully i will do that soon and then you can use this as inspiration for similar adventures.
          If you are interested contact me directly on webmaster [a t] roboblob dot com and i will send you the code that i managed to put together so far.

          Good luck and thanks for your feedback!

          1. Like everyone else, I’m struggling with the ViewModelLocator implementation. I’m definitely interested in your solution and look forward to the write up!

  6. Just thinking out loud here… Would it be possible to do the InDesignMode switch in the Bootstrap?

    Something like:

    public static void InitializeIoc() {

    if (InDesignMode) {
    // Register all mock services
    }
    else {
    // Register all real services
    }

    1. Thanks for your feedback.

      Yes you dont get much of Blendability that way… better is to use d:DataContext for blendability while in bootstrapper keep real entities, but in order for this to work, all Views need clean default constructor, no dependencies in it.

      Hope it helps.
      Cheers.

  7. Hey there,

    I really enjoy all your posts on SL and MVVM. Keep it up!
    I was curious to know about the other solution you had and if I could use it. I just got this one working and kind of like it, although I don’t like having to create a new class for each viewmodel to locate it, but I guess thats a trade-off for getting this good thing to work!

    By the way, the “d:DataContext” thing only seems nescessary in VS 2010 design mode, not for Blend 4. Blend works fine without it.

    Please come back with more info on the other approach, I am really interested!

    Thanks alot for your work.

    1. Hi,

      glad it works for you.
      I will definitely try to post more on the INavigationService approach since it turned out to be better than ViewModelLocator and also i get lot of requests to write about it lately…
      Thanks for your feedback!

    1. Hi Geoff,

      i found out after this article that ViewModelLocator pattern brings more problems that it solves.
      Im planning to write another article on this subject with completely different approach – separate service that will instantiate View and ViewModel and then show them on screen.
      Stay tuned, i think you will find this approach much more natural then ViewModelLocator.

      Thanks for your feedback!

  8. Hi Rob,

    Thanks for such a great article, I thought it was very clear and helpful in explaining the blendability and MVVM.
    Of course, a special thanks to Laurent Bugnion for developing the MVVM Light framework, which makes it a lot easier with implementation of ViewmodelLocator.

    1. Hi Serkan,

      thanks for your comment!

      By the way, I have lately moved away from the concept of ViewModelLocator since i discovered its not good enough for complex MVVM scenarios.
      If you want to see my latest take on Silverlight MVVM and Blendability take a look at my latest posts:

      http://blog.roboblob.com/2010/10/15/combining-silverlight-navigation-framework-and-prism-to-create-mvvm-applications-introduction/
      http://blog.roboblob.com/2010/10/24/introducing-prism-navigation-framework-for-silverlight-mvvm-applications/

  9. Hi, Neat post. There is a problem with your site in internet explorer, would test this IE still is the market leader and a large portion of people will miss your magnificent writing due to this problem.

    1. Hi Abram,

      can you be more specific what kind of problems you have in IE and which version. I tested in IE 8 and it works fine.
      thanks!

Leave a Reply