WPF MVVM 在按钮单击时在视图之间导航

Posted

技术标签:

【中文标题】WPF MVVM 在按钮单击时在视图之间导航【英文标题】:WPF MVVM Navigate between Views on button click 【发布时间】:2019-07-26 06:44:20 【问题描述】:

我正在尝试创建一个 WPF 应用程序,对于导航,我使用的是我在

找到的示例

https://rachel53461.wordpress.com/2011/12/18/navigation-with-mvvm-2/

现在,我需要在单击按钮时从一个 UserControl 导航到另一个。

有人可以指导我如何使用 MVVM 实现这一目标吗?或者我是否应该考虑使用一些导航框架。

【问题讨论】:

【参考方案1】:

这在一定程度上取决于上下文,但很多时候我使用的技术是在某个 ViewModel 中有一个名称类似于“MainContent”的对象(或某种抽象类)。这负责保存要在ContentControl 中显示的内容。

我的 XAML 看起来像这样,其中 Type1ViewType2View 将是 UserControls(vw_Type1vw_Type2 是对其命名空间的引用),然后我将通过设置 @ 在它们之间导航987654328@ 到 Type1ViewModelType2ViewModel 的实例。

<ContentControl Content="Binding MainContent">
    <ContentControl.Resources>
        <DataTemplate DataType="x:Type vm_Type1:Type1ViewModel">
            <vw_Type1:Type1View />
        </DataTemplate>
        <DataTemplate DataType="x:Type vm_Type2:Type2ViewModel">
            <vw_Type2:Type2View />
        </DataTemplate>
    </ContentControl.Resources>
</ContentControl>

这可能会通过ContentControl 之外的一个按钮(或以下示例中的两个按钮)来处理,该按钮向包含MainContent 的 ViewModel 发送一个命令,这只是更改了MainContent 属性,到Type1ViewModelType2ViewModel 的现有或新实例。例如:

private Type1ViewModel _type1ViewModel;
public Type1ViewModel Type1ViewModel

    get  return _type1ViewModel; 
    set
    
        if (_type1ViewModel != value)
        
            _type1ViewModel = value;
            NotifyPropertyChanged();
        
    


private Type2ViewModel _type2ViewModel;
public Type2ViewModel Type2ViewModel

    get  return _type2ViewModel; 
    set
    
        if (_type2ViewModel != value)
        
            _type2ViewModel = value;
            NotifyPropertyChanged();
        
    


...

private ObservableObject _mainContent;
public ObservableObject MainContent

    get  return _mainContent; 
    set
    
        if (_mainContent != value)
        
            _mainContent = value;
            NotifyPropertyChanged();
        
    


...

public InternalDelegateCommand NavigateToType1Command => new InternalDelegateCommand(NavigateToType1);
public InternalDelegateCommand NavigateToType2Command => new InternalDelegateCommand(NavigateToType2);

...

private void NavigateToType1() => MainContent = Type1ViewModel;
private void NavigateToType2() => MainContent = Type2ViewModel;

所以要完成此示例的 XAML:

<Button Content="Type 1" Command="Binding NavigateToType1Command" />
<Button Content="Type 2" Command="Binding NavigateToType2Command" />
<ContentControl Content="Binding MainContent">
    <ContentControl.Resources>
        <DataTemplate DataType="x:Type vm_Type1:Type1ViewModel">
            <vw_Type1:Type1View />
        </DataTemplate>
        <DataTemplate DataType="x:Type vm_Type2:Type2ViewModel">
            <vw_Type2:Type2View />
        </DataTemplate>
    </ContentControl.Resources>
</ContentControl>

(有关InternalDelegateCommand的信息,请参阅我对this question的回复。)

【讨论】:

感谢您的帮助。但我有点困惑 MainContent 需要驻留在哪里。现在,当我按照您的示例并单击按钮时,MainContent 为空且私有 void NavigateToType1() => MainContent = Type1ViewModel,此处 Type1ViewModel 为空。 我发布的一段 C# 代码是 ViewModel 的部分视图,它是主视图的数据上下文(我发布的最后一段 XAML)。 Type1ViewModel 如果您还没有实例化它,它将为空。因此,您可以实例化它并将其保存在内存中(可能在构造函数中),或者您可以尝试private void NavigateToType1() =&gt; MainContent = new Type1ViewModel();

以上是关于WPF MVVM 在按钮单击时在视图之间导航的主要内容,如果未能解决你的问题,请参考以下文章

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

关于使用 Caliburn.Micro MVVM WPF 进行视图导航的建议

我需要导航到另一个视图,其中包含带有 MVVM 的 WPF 中父对象的子对象

导航 MVVM

通过绑定在鼠标单击时导航 WebBrowser

处理 WPF 应用程序中多个视图之间的导航