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
{
    // simplified properties
    public ViewModelBase CurrentView {get; set;}
    public ICommand ViewHomeCommand {get;}
    public ICommand 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.

33 Responses to Switching between Views/UserControls using MVVM

  1. Reureu says:

    Hi Rachel,

    Thank you very much for bringing clarity in the wonderful world of WPF.
    I’m interested in the section about Using a DataTrigger.
    In what part of the XAML file do you place the DataTemplate elements? Under the Resources element?

    Could you please upload the whole code?

    Kind regards,
    Reureu

    • Rachel says:

      Hi Reureu, I usually place the DataTemplates in whatever .Resources block it makes sense to do so. Window.Resources, UserControl.Resources, or occasionally Application.Resources. It all depends on the scope you want it applied to, and how you want your code organized.

  2. Eugene says:

    Hi Rachel. First I bag your pardon for my por English. I begin to develop C# WPF application using Catel MVVM framework now. My application must have: Main Window, 5 views done as UserControls and 5 buttons (on toolbar in MainWindow). These buttons are for switching among views. Each button must turn on corresponding view and turn off the previous displayed view in Main Window. For example if “Display Flowmeter Status View” button is pressed and “Field Settings” view is being displayed in Main Window that moment then “Field Settings” view must be turned off and “Flowmeter Status” view must be displayed in Main Window instead of . And so on. I’ve read your “Switching between Views/UserControls using MVVM” article but I’m a green tyro in Catel. I fear that approach described in your article doesn’t match to Catel. Please tell me if using a your DataTemplate approach for switching among views is fit to my case. Your help will be appreciated highly.

  3. ErazerBrecht says:

    Thanks for sharing your solution!

  4. Eido Askayo says:

    Hi Rachel,
    Thank you very much for this great article, I found it very informative and understandable.

    I would like to ask you a question about a specific scenario:

    Lets say that, further your example, is very large control and is needed to kept alive (cached) in the memory.

    The problem is that every time we set the property of WorkViewUserControl ViewModel (WorkViewModel), the WPF automatically initializes a new instance of WorkViewUserControl, so it very Ineffective.

    I would like to know how the best practice to achieve it.

    • Rachel says:

      Hi Eido,

      I recall doing something custom with a TabControl to cache the ContentPresenter for each tab page so it doesn’t have to be re-created anytime the user switches tabs. Perhaps the same concept could be used at the control-level for your application?

      A copy of the TabControl code can be found here if you’re interested in attempting that as a solution.

      Good luck with it 🙂

  5. John says:

    Hello! I found this article which is exactly what I need to make my module work. I just don’t understand one thing tho (I’m new in MVVM).

    When ViewHomeCommand and ViewWorkCommand are declared, what should be the implementation? or, are they references of something else? I just don’t get what they are, are they ICommand implementations? (I am using MVVM Light Toolkit).

    I would appreciate any heads up or recommendations! 🙂

    • Rachel says:

      Hi John,

      Commands are ICommand implementations that execute some action. For example, ViewHomeCommand might be a RelayCommand that changes the SelectedView object to a HomeViewModel. There is an example of this navigation style in this post if you’re interested in seeing an example.

      Thanks,
      Rachel

  6. Paul Gibson says:

    Hi Rachel,

    I am getting a bit confused with the way this might work. I have a SQL Server database that contains all of the data. My WPF application is essentially a viewer, but I’d like it to become a full CRUD application. The tables in the database are relational, and I had been using stored procedures called by TableAdapters to fill the DataSource layer and bind that to the UI elements. Can you explain or point me to an explanation of this basic diagram in terms of MVVM and the VS IDE? Will I use a DataSet like the IDE seems to want, or does this violate the MVVM? If I use a DataSet, should it mimic the Database, so that the a datatable that is the result of a left join can be two way? Am I missing something entirely?

    Thanks for the great blogging, Paul

    • Rachel says:

      Hi Paul, it sounds like you’re missing the Model layer to your MVVM application. Typically you’d create Model objects for each of the items in your database, and the View would bind to those. ViewModels would also be used to retrieve or save data to and from the database, either directly or through a Data Access Layer in your application. DataSets are useful, but they’re not very good at modeling your business objects.

  7. 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

  8. Yang says:

    Hi Rachel,

    Probably you should think about the situation when you have more than two views. So rather than have a command for each view, you’d better just have one command with an object parameter which suggest which view should be your current view. Then from your xaml code, you can specify your command parameter when you binding your command to your menu item. In this way, you are even able to use key combination to trigger the command to rotate views.

    • Rachel says:

      I agree it is better to have one ChangeView command with a parameter for which view to select instead of having multiple commands for each view, however I was looking to keep things simple in this example 🙂

  9. 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 =)

  10. Dennis says:

    thanks

  11. Bjorn says:

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

  12. 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…

  13. 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 🙂

  14. 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.

  15. 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.

  16. Amit says:

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

  17. 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?

  18. 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.

  19. Yomodo says:

    Thank you for this, just what I need! 🙂

Leave a comment