在MVVM WPF中切换视图

5
我知道我的问题很常见,但是我找到的每个解决方案都不是我真正需要的。这是我的问题:我想在主窗口中能够在不同的用户控件之间切换。我找到的所有解决方案都包括在主窗口中有一个菜单,每个按钮带来相应的用户控件,就像这个例子:https://rachel53461.wordpress.com/2011/12/18/navigation-with-mvvm-2/ 但是我想要的更像是:一开始,主窗口有UserControl1。在UserControl1中,会有一个按钮,用于将主窗口的内容更改为新的用户控件(例如UserControl2)。

enter image description here

主窗口的 XAML。
<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>

我的主窗口的 CS:

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

我的第一个页面的XAML:

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

我的第一个页面视图:

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

我的第一个页面的viewModel:

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();
    }
}

当然他不知道"SelectedViewModel",因为它绑定到主窗口的控件。
我的导航视图模型:
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));
        }
    }

}

非常感谢您的帮助!

1
你需要使用数据模板并将其与嵌入式视图模型关联。然后,您需要为按钮创建一个命令,以触发主窗体视图模型上的“当前”嵌入式视图模型更新,并调用通知属性更改。你的视图模型在哪里?请向我们展示代码。听起来你需要从头开始,即找到一个“WPF和MVVM入门教程”。那就是我开始的方式。 - rory.ap
请分享您尝试的代码,并让我们知道您遇到的任何特定问题。 - Versatile
@rory.ap 这是我的代码(上面的)。 - Json
1个回答

6
您可以例如将对MainViewModel的引用注入到MenuViewMenuViewModel中:

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();
    }
}

好的!但是,它告诉我: 非可调用成员“MenuViewModel”不能像方法一样使用。 - Json
不可调用的成员“MenuViewModel”不能像方法一样使用。 - Json
当我点击其中一个按钮时,用户控件没有改变 :/ - Json
让我们在聊天中继续讨论这个话题。 - Json
我尝试在第2页和第3页之间做同样的事情(第2页上的按钮->转到第3页),但显然我没做对 :/ - Json
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接