WPF MVVM Switching Between Usercontrols

2019-04-17 09:03发布

问题:

I am new to MVVM. I found this artcle and it resolve my haf of problems.

https://social.technet.microsoft.com/wiki/contents/articles/30898.simple-navigation-technique-in-wpf-using-mvvm.aspx

However, I need to navigate from one usercontrol to another from the button click event of one usercontrol not from the button on the main window.

Usercontrol 1:

Usercontrol 2:

This is what I have tried sofar;

class Usercontrol1ViewModel : INotifyPropertyChanged
{
    public ICommand navCommand { get; set; }


    public Usercontrol1ViewModel()
    {
        navCommand = new BaseCommand(navigate);
    }

    private void navigate(object obj)
    {
       NavigationViewModel mainViewModel = new NavigationViewModel();
       mainViewModel.SelectedViewModel = new Usercontrol2ViewModel();
    }

    public event PropertyChangedEventHandler PropertyChanged;

    private void OnPropertyChanged(string propName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propName));
        }
    }
}

NavigationView model class

Class NavigationViewModel : INotifyPropertyChanged
{

    public ICommand btn1Command { get; set; }

    public ICommand btn2Command { get; set; }

    private object selectedViewModel;

    public object SelectedViewModel

    {

        get { return selectedViewModel; }

        set { selectedViewModel = value; OnPropertyChanged("SelectedViewModel"); }

    }



    public NavigationViewModel()
    {

        btn1Command = new BaseCommand(Opencontrl1);

        btn2Command = new BaseCommand(Opencontrl2);

    }

    private void Opencontrl1(object obj)
    {

       SelectedViewModel = new Usercontrol1ViewModel();

    }

    private void Opencontrl2(object obj)
    {

        SelectedViewModel = new Usercontrol2ViewModel();

    }

    public event PropertyChangedEventHandler PropertyChanged;

    private void OnPropertyChanged(string propName)
    {

        if (PropertyChanged != null)

        {

            PropertyChanged(this, new PropertyChangedEventArgs(propName));

        }

    }

}

Main window code behind;

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

Can somebody guide me how to achieve this with MVVM?

回答1:

Try the below code. I used the sample code in the article and I am the author of the MSDN article :)

MainWindow.xaml

<Window.Resources>       
    <DataTemplate DataType="{x:Type local:EmployeeViewModel}">
        <local:EmployeeView/>
    </DataTemplate>
    <DataTemplate DataType="{x:Type local:DepartmentViewModel}">
        <local:DepartmentView/>
    </DataTemplate>
</Window.Resources>
<DockPanel LastChildFill="True">             
    <ContentControl x:Name="Pages" DockPanel.Dock="Right" Content="{Binding SelectedViewModel}"/>
</DockPanel>

NavigationViewModel

class NavigationViewModel : INotifyPropertyChanged
{
    public EmployeeViewModel EmployeeViewModel { get; set; }
    public DepartmentViewModel DepartmentViewModel { get; set; }

    private object selectedViewModel;

    public object SelectedViewModel
    {
        get { return selectedViewModel; }
        set { selectedViewModel = value; OnPropertyChanged("SelectedViewModel"); }
    }


    public NavigationViewModel()
    {
        SelectedViewModel = new EmployeeViewModel(OpenEmp);
    }

    private void OpenEmp(object obj)
    {
        if (obj.ToString() == "Dept")
        {
            SelectedViewModel = new DepartmentViewModel();
        }
    }


    public event PropertyChangedEventHandler PropertyChanged;
    private void OnPropertyChanged(string propName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propName));
        }
    }
}

EmployeeView

 <Grid>
    <StackPanel>
        <TextBlock Text="This is employee view"/>
        <Button Content="Navigate to Dept View" Command="{Binding Navigate}"/>
    </StackPanel>
</Grid>

EmployeeViewModel

 class EmployeeViewModel
{
    private readonly Action<object> navigate;

    public ICommand Navigate { get; set; }
    public EmployeeViewModel(Action<object> navigate)
    {
        Navigate = new BaseCommand(OnNavigate);
        this.navigate = navigate;
    }

    private void OnNavigate(object obj)
    {
        navigate.Invoke("Dept");
    }
}