在 MVVM wpf 中切换视图

Posted

技术标签:

【中文标题】在 MVVM wpf 中切换视图【英文标题】:switching views in MVVM wpf 【发布时间】:2017-02-14 15:20:29 【问题描述】:

我知道我的问题很常见,但我找到的每一个解决方案都不是我真正需要的。这是我的问题:我希望能够在主窗口中的不同用户控件之间切换。我找到的所有解决方案都包括在主窗口中有一个菜单,并且每个按钮都带有相应的 userControl,例如:https://rachel53461.wordpress.com/2011/12/18/navigation-with-mvvm-2/

但我想要的更像是:在开始时,主窗口将 UserControl1 放入其中。在 userControl1 中会有 1 个按钮使用新的 userControl(例如 userControl2)更改主窗口的内容

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

我的 mainWindow 的 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”,因为它绑定到 mainWindow 的控件

我的导航视图模型:

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


非常感谢您的帮助!

【问题讨论】:

您需要使用数据模板并将它们与您的嵌入式视图模型相关联。然后,您需要为按钮创建一个命令以在主窗体的视图模型上触发,该视图模型更新“当前”嵌入式视图模型并调用通知属性已更改。你的视图模型在哪里?请向我们展示代码。听起来您需要从头开始,即找到“初学者的 WPF 和 MVVM”教程。我就是这样开始的。 分享您尝试过的代码,如果您遇到任何具体问题,请告诉我们。 @rory.ap 这是我的代码(上面) 【参考方案1】:

例如,您可以注入 MenuViewMenuViewModel 并引用 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();
    

【讨论】:

好的!但是,它告诉我:不可调用的成员“MenuViewModel”不能像方法一样使用。 不可调用的成员 'MenuViewModel' 不能像方法一样使用 aaaahhhh 是的,我应该看到它。但它不起作用。也许我的一个 userControl 中的 dataContext 有问题... 当我点击其中一个按钮时,userControl 不会改变:/ 让我们continue this discussion in chat。

以上是关于在 MVVM wpf 中切换视图的主要内容,如果未能解决你的问题,请参考以下文章

MVVM + WPF - 为具有多个视图的 ViewModel 设计

使用带有棱镜的 MVVM 在视图之间切换

WPF(MVVM):从 Viewmodel 关闭视图?

在 UserControl WPF MVVM caliburn 内的 UserControl 之间切换

在 WPF MVVM 中的视图之间导航

如何在 WPF / MVVM 中对绑定到相同实例的两个列表视图进行不同选择