【问题标题】:What is the best way to switch views/usercontrols in MVVM-light and WPF?在 MVVM-light 和 WPF 中切换视图/用户控件的最佳方式是什么?
【发布时间】:2011-09-01 03:37:31
【问题描述】:

我对 WPF 和 MVVM 比较陌生,我发现最难的事情是如何在应用程序中简单地切换用户控件或视图。

在 winforms 中,要让控件自行删除,您可以简单地说 this.Parent.Controls.Remove(this);

在 WPF 中没有通用父控件,您必须将其类型转换为特定类型(即网格),然后将其删除。

这似乎也打破了 MVVM 架构。我也尝试过数据模板和内容展示器,它们运行良好,除了我无法从代码中更改数据上下文,因为数据上下文始终是视图模型定位器。

页面现在是 WPF 中可接受的方式吗?如果我有一个带有自定义 usecontrol 的网格并且我想根据 viewModel 中的某个变量来切换它怎么办?在 WPF 中似乎无法轻松完成最简单的任务。

【问题讨论】:

    标签: wpf mvvm-light


    【解决方案1】:

    你可以在你的父 ViewModel 中这样做。

    例如,如果您的页面(称为 PageViewModel)有两个视图(ViewModelAViewModelB),您将在 PageViewModel 上拥有一个名为 CurrentView 的属性,这将确定哪个视图是可见的。当PageViewModel.CurrentView 设置为ViewModelA 的实例时,则使用ViewA 的DataTemplate 来绘制内容。当设置为ViewModelB的实例时,会显示ViewB的DataTemplate。

    <DataTemplate DataType="{x:Type local:PageViewModel}">
        <ContentControl Content="{Binding CurrentView}" />
    </DataTemplate>
    
    <DataTemplate DataType="{x:Type local:ViewModelA}">
        <TextBlock Text="I'm ViewModelA" />
    </DataTemplate>
    
    <DataTemplate DataType="{x:Type local:ViewModelB}">
        <TextBlock Text="I'm ViewModelB" />
    </DataTemplate>
    

    最好从父视图调用切换视图命令(在本例中为 PageViewModel 的 DataTemplate),但是如果您想从 ViewModelA/B 中切换视图,您可以连接事件在创建对象时手动 (CurrentView.ChangeViewCommand = this.ChangeViewCommand) 或查看消息传递系统。 MVVM Light 有一个简单的 Messenger 类,我发现它相当容易使用,或者 Prism 有一个更高级的 EventAggregator

    如果您想为同一个 ViewModel 切换视图,我建议您使用 Mode 属性来确定要使用的视图。例如:

    <DataTemplate x:Key="ViewA" DataType="{x:Type local:MyViewModel}">
        <TextBlock Text="I'm ViewModelA" />
    </DataTemplate>
    
    <DataTemplate x:Key="ViewB" DataType="{x:Type local:MyViewModel}">
        <TextBlock Text="I'm ViewModelB" />
    </DataTemplate>
    
    <DataTemplate DataType="{x:Type local:MyViewModel}">
        <ContentControl Content="{Binding }">
            <ContentControl.Style>
                <Style TargetType="{x:Type ContentControl}">
                    <Setter Property="ContentTemplate" Value="{StaticResource ViewA}" />
                    <Style.Triggers>
                        <DataTrigger Binding="{Binding Mode}" Value="2">
                            <Setter Property="ContentTemplate" Value="{StaticResource ViewB}" />
                        </DataTrigger>
                    </Style.Triggers>
                </Style>
            </ContentControl.Style>
        </ContentControl>
    </DataTemplate>
    

    编辑

    其实我经常看到这类问题出现,所以如果有人有兴趣,请发帖here

    【讨论】:

    • 这几乎就是我想要的。如果我理解正确,您可以使用 DataTriggers 绑定到一个值,然后即时切换内容。这是否适用于 ContentPresenter 等其他控件?
    • @JReed 当然,我不明白为什么不这样做。在第二个示例中,我正在切换 ContentControlContentTemplate 属性,但您可以切换基于触发器的任何控件上的几乎任何属性
    • @EmpereurAiman 那么负责创建虚拟机的任何代码都应该将正确的参数传递给它:)
    • @EmpereurAiman DataTemplate 告诉 WPF 如何绘制 ViewModel。它实际上并没有创建它。那是其他东西的责任......通常对我来说,如果它是我的应用程序中的最高级别,它将是背后的代码,否则它将是另一个 ViewModel。如果需要,还有更完整的代码示例 here
    • 谢谢瑞秋。我检查了您的博客,您使用的视图模型优先方法为我解决了很多问题。 :)
    猜你喜欢
    • 1970-01-01
    • 2019-01-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多