Search code examples
wpfmvvmdatatemplate

WPF mvvm DataTemplates change View from UserControl


I am new to WPF and the MVVM pattern. I am trying to build a 'step by step' or 'wizard' like application. So the user should first login then select some data and finally the selected data should be stored somewhere. (This flow never changes!) However I decided to use DataTemplates and different ViewModels for each Template and a MainViewModel for the Window which populates the Templates. (Think this should be ok regarding to different Posts here)

But now my problems are starting. I know how I can change the current view from the MainViewModel BUT I want to change the current View from the inner ViewModel. And I want to be able to collect data from one inner ViewModel to another and I have no clue how this can work.

MainViewModel:

public class MainWindowViewModel : ViewModelBase
{
    public ViewModelBase CurrentView {get; set;}

    public MainWindowViewModel()
    {
        CurrentView = new ViewModelA;
    }
}

XAML:

<Window x:Class="PUSEImporter.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:VM="clr-namespace:PUSEImporter.ViewModel"
        xmlns:V="clr-namespace:PUSEImporter.View">
    <Window.DataContext>
        <VM:MainWindowViewModel />
    </Window.DataContext>
    <Window.Resources>
        <DataTemplate DataType="{x:Type VM:ViewModelA}">
            <V:Detail />
        </DataTemplate>
        <DataTemplate DataType="{x:Type VM:ViewModelB}">
            <V:Overview />
        </DataTemplate>
    </Window.Resources>
        <ContentPresenter Content="{Binding CurrentView}"/>
</Window>

So think about a button in ViewModelA (or the View from ViewModelA) and now I want to switch to ViewModelB when someone clicks on the button. And not enough the data which is collected by ViewModelA should also be available in ViewModelB.

Is this possible and the preferred way of using this techniques or do I misunderstand some concepts? (And if this is true how should i handle things like that?)

Thanks in advance!


Solution

  • There are many ways to achieve what you want. In MVVM, there's one view model to each view... therefore, if your main view has a child view, then your main view model should have a property of the type of another view model. In this instance, you can add a delegate to the child view model and register a handler for it in the main view model.

    This will enable you to effectively pass a signal to the main view model from the child view model, which you can react to in the parent view model in any way you want to. Rather than explain the whole story again here, please see my answers from the Passing parameters between viewmodels and How to call functions in a main view model from other view models? posts here on Stack Overflow for more information on how to achieve this.