switching views in MVVM wpf

14,365

You could for example inject the MenuView or MenuViewModel with a reference to the MainViewModel:

MainWindow.xaml.cs:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        var viewModel = new NavigationViewModel();
        viewModel.SelectedViewModel = new MenuViewModel(viewModel);
        this.DataContext = viewModel;
    }
}

MenuViewModel.cs:

class MenuViewModel
{
    public ICommand EmpCommand { get; set; }
    public ICommand DeptCommand { get; set; }

    private readonly NavigationViewModel _navigationViewModel;

    public MenuViewModel(NavigationViewModel navigationViewModel)
    {
        _navigationViewModel = navigationViewModel;
        EmpCommand = new BaseCommand(OpenEmp);
        DeptCommand = new BaseCommand(OpenDept);
    }

    private void OpenEmp(object obj)
    {
        _navigationViewModel.SelectedViewModel = new EmployeeViewModel();
    }
    private void OpenDept(object obj)
    {
        _navigationViewModel.SelectedViewModel = new DepartmentViewModel();
    }
}

MenuView.xaml.cs:

public partial class MenuView : UserControl
{
    public MenuView()
    {
        InitializeComponent();
    }
}
Share:
14,365
Json
Author by

Json

Updated on June 22, 2022

Comments

  • Json
    Json almost 2 years

    I Know that my problem is a common one but every solution I found is not the one I really need. Here is my problem : I want to be able to switch between different usercontrol in the mainWindow. All the solution I found consist of having a menu in the main window and every button brings the corresponding userControl, like this exemple : https://rachel53461.wordpress.com/2011/12/18/navigation-with-mvvm-2/

    But what i want is more like : at the begining, the mainwindows has the UserControl1 into it. In the userControl1 there would be 1 buttons who change the content of the mainWindow with a new userControl (userControl2 for instance)

    enter image description here

    the xaml of mainWindow

    <Window x:Class="DataTemplateSO_Learning.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:local="clr-namespace:DataTemplateSO_Learning"
            Title="MainWindow" Height="350" Width="525">
        <Window.Resources>       
            <DataTemplate DataType="{x:Type local:EmployeeViewModel}">
                <local:EmployeeView/>
            </DataTemplate>
            <DataTemplate DataType="{x:Type local:DepartmentViewModel}">
                <local:DepartmentView/>
            </DataTemplate>
            <DataTemplate DataType="{x:Type local:MenuViewModel}">
                <local:MenuView/>
            </DataTemplate>
        </Window.Resources>
        <DockPanel LastChildFill="True">
            <ContentControl x:Name="Pages" DockPanel.Dock="Right" Content="{Binding SelectedViewModel}"/>
        </DockPanel>
    </Window>
    

    the cs of my mainWindow :

    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            Pages.Content = new MenuView();
            this.DataContext = new NavigationViewModel();
        }
    }
    

    the xaml of my first page :

    <UserControl x:Class="DataTemplateSO_Learning.MenuView"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
                 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
                 xmlns:local="clr-namespace:DataTemplateSO_Learning"
                 mc:Ignorable="d" 
                 d:DesignHeight="300" d:DesignWidth="300">
        <DockPanel LastChildFill="True">
            <StackPanel x:Name="navigation" DockPanel.Dock="Left" VerticalAlignment="Center">
                <Button Content="Employee" Command="{Binding EmpCommand}"></Button>
                <Button Content="Department" Command="{Binding DeptCommand}"></Button>
            </StackPanel>
        </DockPanel>
    </UserControl>
    

    my first page View :

    public partial class MenuView : UserControl
    {
        public MenuView()
        {
            InitializeComponent();
            this.DataContext = new MenuViewModel();
        }
    }
    

    the viewModel of my first page :

    class MenuViewModel 
    {
        public ICommand EmpCommand { get; set; }
        public ICommand DeptCommand { get; set; }
    
        public MenuViewModel()
        {
            EmpCommand = new BaseCommand(OpenEmp);
            DeptCommand = new BaseCommand(OpenDept);
        }
    
        private void OpenEmp(object obj)
        {
            SelectedViewModel = new EmployeeViewModel();
        }
        private void OpenDept(object obj)
        {
            SelectedViewModel = new DepartmentViewModel();
        }
    }
    

    of course he doesn't know "SelectedViewModel" because it's bind to the control of mainWindow

    my navigationViewModel :

    class NavigationViewModel : INotifyPropertyChanged
    {
        private object selectedViewModel;
    
        public object SelectedViewModel
        {
            get
            {
                return selectedViewModel;
            }
            set
            {
                selectedViewModel = value;
                OnPropertyChanged("SelectedViewModel");
            }
        }
    
        public event PropertyChangedEventHandler PropertyChanged;
        private void OnPropertyChanged(string propName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propName));
            }
        }
    
    }
    

    Thank you very much for your help !