MVVM – Correct Way to Switch Between Views in WPF

mvvmviewwpf

An example is switching the main view according to the selected item in a hamburger menu. Also sometimes it is just a small part of the GUI that changes according to the application state or according to user interaction with other parts of the GUI.

In WebForms days we used to create a tab control and hide the tab buttons bars and change the current tab page programmatically. Or stack the views on top of each other in design and in runtime hide all but one.

In WPF and MVVM I've seen people creating DataTemplate for each view, attach each to a view model and switch by changing the bound object to be of a different view model type and so the view changes.

I can see why that is a good idea for the hamburger menu views, but for some other cases, there are not necessarily a view model for each view. And in that case I'd like to escape having to create dummy view models for each view just to be able to switch between them rather than really having different types of data that I need to bind to each view.

Am I right to be concerned about this design detail?

Anyone had the same situation? What was the way you achieved the switch view effect?

In general, assuming there is no different type of data attached to each of the views to switch between, is it a correct practice to create view models just for something that is purely GUI? In other words, is view models more coupled to the data and what kind of data is available or to the GUI and the types of view we need to cover? And should we write the code for changing views on certain triggers in code behind in case we agreed that this is purely GUI and view models are not to be involved?

Best Answer

In MVVM, the ViewModel contains the state of your UI. The View is merely a reflection of that state. This reflection of state is accomplished via databinding, converters, styles, etc.

I think what you want is a state variable on your ViewModel and have visibility of various UI bits bound to that state.

First, define a state enum and create a property on your VM:

    enum ViewState
    {
        State1,
        State2
    }

    class MyVM
    {
        public ViewState ViewState {get;set;}
    }

Then in your view, you can hide/show UI elements using triggers:

    <StackPanel>
        <StackPanel.Style>
            <Style TargetType="StackPanel">
                <Setter Property="Visibility" Value="Collapsed" />
                <Style.Triggers>
                    <DataTrigger Binding="{Binding Path=ViewState}" Value="{x:Static local:ViewState.State1}">
                        <Setter Property="Visibility" Value="Visible" />
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </StackPanel.Style>
    </StackPanel>
Related Topic