Switching between Views/UserControls using MVVM

I often like to browse questions tagged with WPF or MVVM on StackOverflow, and one question I see come up frequently is how to switch between Views or UserControls in MVVM.

Once you get used to the fact that the ViewModels run your application, it is very simple. Your ViewModel contains a property which defines your CurrentView and to switch views you simply switch your ViewModel’s properties.

There is more than one way to do this, but I’ll show  two common examples.

Using a DataTemplate

The simplest way is to use a DataTemplate. Lets say you have a window with two screens you want to switch between: Home and Work. You have a Menu at the top with two options: View Home Page and View Work Page. Your ViewModel behind this page would have a CurrentView property, along with two commands: ViewHomeCommand and ViewWorkCommand.

public class AppViewModel
{
    public ViewModelBase CurrentView {get; set;}
    public ViewHomeCommand {get;}
    public ViewWorkCommand {get;}
}

The page’s content would simply be a ContentControl with it’s content bound to CurrentView.

<ContentControl Content="{Binding CurrentView}" />

Now all you need to do is define two DataTemplates, one for the Home and one for the Work

<DataTemplate DataType="{x:Type HomeViewModel}">
    <TextBlock Text="This is the Home Page" />
</DataTemplate>
<DataTemplate DataType="{x:Type WorkViewModel}">
    <localControls:WorkViewUserControl />
</DataTemplate>

When you execute ViewHome/Work commands, all it is doing is setting the CurrentView to an instance of either HomeViewModel, or WorkViewModel. That ViewModel is getting bound to the ContentControl, and the DataTemplate is used to determine how to display the object.

Using a DataTrigger

Sometimes you may want to switch views based on a property instead of a type. Lets say you’re viewing a list of Consumers, and you want to display one View if the consumer is a Business, and a different View if the Consumer is a Person. In this case, you would use a DataTrigger

<DataTemplate x:Key="PersonTemplate" DataType="{x:Type local:ConsumerViewModel}">
     <TextBlock Text="I'm a Person" />
</DataTemplate> 

<DataTemplate x:Key="BusinessTemplate" DataType="{x:Type local:ConsumerViewModel}">
     <TextBlock Text="I'm a Business" />
 </DataTemplate>

<DataTemplate DataType="{x:Type local:ConsumerViewModel}">
     <ContentControl Content="{Binding }">
         <ContentControl.Style>
             <Style TargetType="{x:Type ContentControl}">
                 <Setter Property="ContentTemplate" Value="{StaticResource PersonTemplate}" />
                 <Style.Triggers>
                     <DataTrigger Binding="{Binding ConsumerType}" Value="Business">
                         <Setter Property="ContentTemplate" Value="{StaticResource BusinessTemplate}" />
                     </DataTrigger>
                 </Style.Triggers>
             </Style>
         </ContentControl.Style>
     </ContentControl>
 </DataTemplate>

Here we have a DataTemplate for a Consumer object which defaults to the PersonTemplate. In a DataTrigger, it checks to see if the ConsumerType is a Business and if so switches to a BusinessTemplate. All you have left to do is bind the Consumer object to a ContentControl to display it.

<ContentControl Content="{Binding CurrentConsumer}" />

Summary

Switching between views using MVVM isn’t hard at all. You just need to remember that the ViewModel is driving the application, not the View. The way I see it, your application should be able to run through a command-line interface, so everything your application needs to know about its state should be in the ViewModels somewhere. This includes the current view.

20 Responses to Switching between Views/UserControls using MVVM

  1. Yomodo says:

    Thank you for this, just what I need! :)

  2. uri247 says:

    Thank you for this. Excellent article. As I mentioned in SO, using DataTemplateSelector (described here: http://msdn.microsoft.com/en-us/library/ms742521.aspx) is also a good direction to explore.

    • Rachel says:

      Glad you liked the article :)

      I usually use a DataTemplateSelector for Silverlight since it doesn’t support implicit DataTemplates (I’m not using 5.0 yet), however I prefer using DataTemplates for WPF since they’re simpler and there’s less code involved.

  3. Benjamin says:

    How would you handle launching a new window? Say I have a login view, which then launches the main window for the app. Any ideas?

  4. Amit says:

    Great work, thanks a ton – just what I needed.

  5. Massimiliano says:

    Dear Rachel,
    i’ve a question: but if CurrentView Obj is of ViewModelBase type, how can i set CurrentView as new HomePageViewModel type?
    Regards, Maximilian.

    • Rachel says:

      Hi Maximilian,

      All the ViewModels, including HomePageViewModel, inherit from ViewModelBase so can be used anywhere a ViewModelBase object is expected.

      I would recommend always having some kind of base class or interface for your content ViewModels with this kind of design so you can provide generic functionality if needed, such as calling CurrentViewModel.Load or binding to CurrentViewModel.DisplayName.

  6. Jeff T says:

    Hi Rachel

    Thanks for these articles – I like your writing style . I’m just getting into WPF coming over from Winforms and your worked examples are great. So it’s a new workd for me. You manage to explain the subjects in a way which makes it both easy to understand and enjoyable to read.

  7. Test says:

    can u please give sample example … :)

    • Rachel says:

      Sorry for taking so long to reply. I actually have an example of this on a similar blog article here. Just scroll to the bottom of the post and there’s a link to download the sample code :)

  8. Ahmad says:

    Hi,
    I want to open a custom dialog box or some child window if I selected an item in main window and want to transfer control to dialogbox/child window. I searched a lot on web but I could not find any straightforward approach. I am working with WPF and MVVM light tool kit. I am quite new in this field.

    In main window, I have list of items and I want to open a detailed version of selected item in dialog box / child window and I want to edit my item in dialogbox / child window.

    I want to have Save and Cancel button on dialogbox / child window.

    Can you suggest me right way of doing this kind of task.

    Thanks…

  9. Bjorn says:

    Thanks for putting this on the net, really helped me!

  10. Dennis says:

    thanks

  11. Scott says:

    Shouldn’t “TargetType” be “DataType”? =)

    • Rachel says:

      You’re right, it should be. That’s what I get for typing this stuff up freehand without using a compiler to check the syntax….

      Thanks Scott =)

  12. dolphe says:

    Hello Rachel,

    This example works until you try to access commands located in the “grand-parent” datacontext.

    I have a user control (child) nested within another user control (parent). Each has its own datacontext. However I would like a button on the child to “trigger” a command located in the parent.
    I looked online, but no success.

    Thanks

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 107 other followers

%d bloggers like this: