繁体   English   中英

WPF/MVVM:在视图之间切换

[英]WPF/MVVM: switching between views

我正在尝试学习 WPF/MVVM,目前正在研究如何在视图之间切换。 我首先在互联网上寻找一些例子来学习。 我正在使用的一个非常简单:两个视图(名为“主页”和“帐户”)仅显示 label,以保持 xaml 和 VM 简单,以及一个主 Z05B8C74CBD96FBF2DE4C1A352702FBF4 视图使用两个按钮在视图之间切换。

DataTemplates 在 App.xaml 文件(连同命名空间)中声明,因此它们应该是整个项目的全局:

<Application.Resources>
    <DataTemplate DataType="{x:Type viewmodels:HomeViewModel}">
        <views:HomeView/>
    </DataTemplate>
    <DataTemplate DataType="{x:Type viewmodels:AccountViewModel}">
        <views:AccountView/>
    </DataTemplate>
</Application.Resources>

按照我的理解,这个技巧是由第三个虚拟机(称为 MainViewModel.cs)完成的,它实现了一个 SelectedViewModel 属性,该属性跟踪必须显示的虚拟机,以及绑定到按钮的 ICommand:

        private BaseViewModel _selectedViewModel;
        public BaseViewModel SelectedViewModel
        {
            get { return _selectedViewModel; }
            set
            {
                _selectedViewModel = value;
                OnPropertyChanged(nameof(SelectedViewModel));
            }
        }
        public ICommand UpdateViewCommand { get; set; }

MainWindow.xaml 看起来像这样:

        <ContentControl Grid.Row="0" Content="{Binding SelectedViewModel}"/>

        <StackPanel Grid.Row="1" Orientation="Horizontal" HorizontalAlignment="Center">
            <Button Margin="10" Width="200" Content="Home" Command="{Binding UpdateViewCommand}" CommandParameter="Home"/>
            <Button Margin="10" Width="200" Content="Account" Command="{Binding UpdateViewCommand}" CommandParameter="Account"/>
        </StackPanel>

在单独的 class 文件 (UpdateViewModel.cs) 中,UpdateViewModel class 实现 Execute 方法,如下所示:

        public void Execute (object parameter)
        {
            if (parameter.ToString() == "Home")
            {
                viewModel.SelectedViewModel = new HomeViewModel();
            }
            else if (parameter.ToString() == "Account")
            {
                viewModel.SelectedViewModel = new AccountViewModel();
            }
        }

我希望我已经给出了这个想法,而不会让你感到厌烦。 这一切都有效,让我了解基础知识。 现在我想尝试一种变体,即采用一个视图(“帐户”视图)并实现一个可以直接切换到另一个视图的按钮。 我以为我所要做的就是将按钮绑定到 UpdateViewModel class,最初我修改了 Account.xaml 代码如下:

        <Button Content="Button" Command="{Binding Path=UpdateViewCommand}" CommandParameter="Home"/>

程序运行,但是当我单击帐户视图中的按钮时,没有任何反应。 所以我把它改成了更复杂的东西:

    <UserControl.DataContext>
        <src:MainViewModel/>
    </UserControl.DataContext>
...
    <Button Content="Button" Command="{Binding Path=UpdateViewCommand}" CommandParameter="Home"/>

但结果是一样的。 我怀疑它与绑定有关,但看不到如何更改它。 有人可以帮忙吗?

欢迎来到 SO!

您的按钮绑定是相对于当前 DataContext 完成的,因此绑定到 AccountView 中的 UpdateViewCommand(例如)将尝试绑定到 AccountViewModel 中的 UpdateViewCommand,而不是 MainViewModel。

有两种方法可以解决这个问题。 首先是更改按钮绑定以绑定到父视图 model :

<Button Content="Button" Command="{Binding Path=DataContext.UpdateViewCommand, RelativeSource={RelativeSource AncestorType={x:Type local:MainWindow}}}" CommandParameter="Home"/>

当然,这里的一个主要缺点是您的子视图所在的视觉层次结构可能并不总是像这样可预测。

第二种(更好的)方法是将 UpdateViewCommand 处理程序添加到您的每个子视图模型,然后让它们将控制权传递给您实际想要处理的任何内容。 在实践中,您通常会为所有孩子创建一个基本 class 以减少代码重复,并且您会创建一个服务(例如 INavigationService)供他们调用。 然后,您的 MainViewModel (例如)将实现此接口,并且您将使用依赖注入在创建子视图模型时将该引用注入到子视图模型中(或者,如果您不希望,则将父视图模型直接传递给它们的构造函数使用完整的 DI 框架)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM