repost: MVVM, providing the Association of View to ViewModel

Jason Rainwater posted a nice summary of the ways in which you can hook up the View and the ViewModel:

May 26

MVVM, providing the Association of View to ViewModel

Hello everyone!

As stated in my previous post, today I will be talking about the different ways we can associate a ViewModel (or any other type of middle object in the MV? design patterns) to the View.

When we look at the UI design patterns we almost always have a View and a middle object, whether it be a ViewModel, Presenter, Controller, Presentation Model, or other newly thought up facilitators, their has to be some sort of association between them.  Today I will show two different ways that we can associate a View to a ViewModel.

The first is my personal favorite and that is using a DataTemplate.  A DataTemplate is a way we can provide a visual representation of any object.  The object in our case is the ViewModel.

    1: <DataTemplate DataType="{x:Type vms:PersonViewModel}">
    2:     <vws:PersonView />
    3: </DataTemplate>

What this does is allows us to use a ViewModel as content and have it resolve the PersonView as the visual to be used.  The cool thing about this is that because the View is the representation of the DataTemplate the View will automatically have a DataContext set to the ViewModel that was set as Content.  So inside the View we can <TextBlock Text="{Binding PersonModel.FirstName}"/> and the binding will work.  This to me is the way to keep the most separation of visuals and behavior.  The View knows nothing directly about the ViewModel and the ViewModel knows nothing directly about the View.  If you create a new View you can just inject a new DataTemplate targeted to the same type and you will have a new Visual for your ViewModel.

The drawback to this is that you do have a full separation so if you need a few coupled items you may have to utilize some other concepts or break the separation by having references back and forth between the View and ViewModel.

The second way to provide the association is using Constructor Injection to the ViewModel and instance of the View.  The code may look something like this.

    1: public class PersonViewModel
    2: {
    3:     private IPersonView _view;
    4:  
    5:     public IPersonView View
    6:     {
    7:         get
    8:         {
    9:             return _view;
   10:         }
   11:     }
   12:  
   13:     public PersonViewModel(IPersonView view)
   14:     {
   15:         _view = view;
   16:  
   17:         _view.DataContext = this;
   18:     }
   19: }

What this does is allows the ViewModel to contain an instance of the View so that it can do things like utilizing events to it, making method calls and such.  The way we would utilize this is by using either concrete instantiation or Dependency Injection resolution.

    1: PersonViewModel viewModel = UnityContainer.Resolve<PersonViewModel>();
    2:  
    3: NavigationManager.NavigateTo(viewModel.View);

Whichever view is registered with the container is the View that will get used so we can still provide different Views for the same ViewModel in this case.  This gives us more access to things on the View but also tightly couples us a little more.  This is not a bad thing but it may be too much for your needs depending on the project.  This also "looks" more like a Presenter than a ViewModel at this point.

The key to the semantics of these different interactions is the difference between a ViewModel and a Presenter.  Generally the second way looks more like a Presenter, but we call is a ViewModel.  I do not think it really matters what we call it as long as certain guidelines are followed.  Things like using Binding.  We can call it a Controller with Binding if we want as along as we adhere to utilizing Binding.

I hope this information is useful and have a good day!