在 MVVM-light 和 WPF 中切换视图/用户控件的最佳方法是什么?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6114479/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 22:52:23  来源:igfitidea点击:

What is the best way to switch views/usercontrols in MVVM-light and WPF?

wpfmvvm-light

提问by JReed

I'm relatively new to WPF and MVVM and the hardest thing I have found is how to simply switch a usercontrol or a view in an application.

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

In winforms, to have a control remove itself you would simple say this.Parent.Controls.Remove(this);

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

In WPF there is no generic Parent control, you would have to typecast it to the specific type (i.e. Grid) and then remove it.

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

This also seems to break the MVVM architecture. I have also tried data templates and content presenters, which work well, except for the fact that I can't change the datacontext from code, since the datacontext is always the viewmodellocator.

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

Are pages the acceptable way to do this in WPF now? What if I had a grid with a custom usecontrol and I wanted to switch it based on some variable in the viewModel? It seems like the simplest tasks cannot be accomplished easily in WPF.

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

回答by Rachel

You would do so in your parent ViewModel.

你会在你的父 ViewModel 中这样做。

For example, if your page (call it PageViewModel) had two views (ViewModelAand ViewModelB), you would have a property on PageViewModelcalled CurrentView, and this would determine which View is visible. When PageViewModel.CurrentViewis set to an instance of ViewModelA, then ViewA's DataTemplate is used to draw the content. When it's set to an instance of ViewModelB, ViewB's DataTemplate is displayed.

例如,如果您的页面(称为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>

It would be ideal to call the switch views command from the parent view (in this case the DataTemplate for the PageViewModel), however if you wanted to switch views from within ViewModelA/B, you can either hook up the event manually when the objects get created (CurrentView.ChangeViewCommand = this.ChangeViewCommand) or look into a messaging system. MVVM Light has a simple Messengerclass which I found was fairly easy to use, or Prism has a more advanced EventAggregator

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

If you want to switch Views for the same ViewModel, I would recommend a Mode property that gets used to determine which view to use. For example:

如果您想为同一个 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>

EDIT

编辑

I actually see this kind of question come up a lot, so posted something about it hereif anyone is interested

我实际上看到这种问题经常出现,所以如果有人感兴趣,请在此处发布有关它的内容