在 MVVM WPF 应用程序中处理导航

Posted

技术标签:

【中文标题】在 MVVM WPF 应用程序中处理导航【英文标题】:Handling Navigation in MVVM WPF application 【发布时间】:2013-03-15 06:25:42 【问题描述】:

我正在开发一个遵循 MVVM 的 WPF 应用程序。现在我正在以下列方式处理视图导航。 主窗口视图

<Border>
    <StackPanel>
    <local:Home
               Content="Binding CurrentView,Converter=StaticResource ViewConverterHome, UpdateSourceTrigger=PropertyChanged"/>
    <local:Page1
            Content="Binding CurrentView,Converter=StaticResource ViewConverterPage1, UpdateSourceTrigger=PropertyChanged"/>
    <local:Page2
        Content="Binding CurrentView,Converter=StaticResource ViewConverterPage2, UpdateSourceTrigger=PropertyChanged"/>
    </StackPanel>

</Border>

Home、Page1、Page2 是 3 个视图。 HomeVM,Page1VM,Page2VM 是视图对应的视图模型。有一个名为 ApplicationViewModel 的类,其中包含 CViewModelBase 类型的 CurrentView 属性,它是所有三个视图模型的父类。 ApplicationViewModel 以如下方式处理导航

   private void OnUserInputNextClicked(object sender, OperationInformationChangedEventArgs e)
    
        do
        
            if (this.CurrentView is HomeVM)
            
                this.CurrentView = null;
                Page1VM page1 = new Page1VM("BNM", "MATH HONS", "13");
                page1.NextCilcked += new EventHandler<OperationInformationChangedEventArgs>(OnUserInputNextClicked);
                page1.BackCilcked += new EventHandler<OperationInformationChangedEventArgs>(OnUserInputBackClicked);
                this.CurrentView = page1;
                break;
            

            if (this.CurrentView is Page1VM)
            
                this.CurrentView = null;
                Page2VM page2 = new Page2VM("Kolkata", "Monoj", "Itachuna");
                page2.NextCilcked += new EventHandler<OperationInformationChangedEventArgs>(OnUserInputNextClicked);
                page2.BackCilcked += new EventHandler<OperationInformationChangedEventArgs>(OnUserInputBackClicked);
                this.CurrentView = page2;
                break;
            
            if (this.CurrentView is Page2VM)
            
                this.CurrentView = null;
                HomeVM home = new HomeVM("Anirban", "30");
                home.NextCilcked += new EventHandler<OperationInformationChangedEventArgs>(OnUserInputNextClicked);
                this.CurrentView = home;
                break;
            
         while (false);
    

导航运行良好;但是处理消失的视图并没有被调用。所以所有的视图都活到最后。有什么办法可以防止这种情况发生吗?

【问题讨论】:

【参考方案1】:

您的视图将始终存在,因为您使用 XAML 将每个视图的副本添加到您的 UI,即使其中包含的 Content 可能不存在

通常我将使用ContentControl 来显示内容,而不是为每种内容类型创建一个控件实例,并且我将使用DataTemplates 告诉 WPF 如何绘制每种类型的内容。

例如,

<Window.Resources>
    <DataTemplate DataType="x:Type local:HomeVM">
        <local:Home Content="Binding " />
    </DataTemplate>
    <DataTemplate DataType="x:Type local:Page1VM">
        <local:Page1 Content="Binding " />
    </DataTemplate>
    <DataTemplate DataType="x:Type local:Page2VM">
        <local:Page2 Content="Binding " />
    </DataTemplate>
</Window.Resources>

<Border>
    <StackPanel>
        <ContentControl Content="Binding CurrentView" />
    </StackPanel>
</Border>

这样,您在 VisualTree 中只有一个 Content 实例,而 DataTemplate WPF 用户可以根据它的 DataType 绘制您的内容更改。

如果您有兴趣查看完整的代码示例,我的博客上有example of this kind of navigation with WPF

【讨论】:

【参考方案2】:

您需要更改 MainWindow 的 DataContext。这取决于您的集成。当我创建一个 MVVM 应用程序时,我所做的就是将 MainWindow 对象传递给每个视图构造函数。每当我必须移动到下一页(比如在下一个按钮上)时,我都会将 MainWindow 对象 DataContext 更改为新视图。

类似的东西。

public PageOneViewModel


    private MainWindow _mainWindow;
    public PageOneViewModel(MainWindow mainWindow)
    
         // Here I am saving MainWindow object.
         _mainWindow = mainWindow;
    

    public OnNext()
    
         // Here I am changing the view.
         MainWindow.DataContext = new PageTwoViewModel(_mainWindow);
    

【讨论】:

毕竟 MainWindow 是一个视图;我不确定是否应该将视图对象传递给 viewModel 构造函数。 MainWindow 不是视图。它实际上是一个承载不同视图的窗口。好吧,这取决于您的实施。我这样做了,这行得通,没有任何规则被这个打破。【参考方案3】:

您考虑过使用 Frame 吗?

<Frame Name="YourFrame" Navigated="OnNavigated"/>

然后你就可以打电话了

YourFrame.CanGoBack()、YourFrame.GoBack()

等等

【讨论】:

【参考方案4】:

这里是link 对我使用工作源代码的类似问题的回答。我使用的技术有点类似于 Faisal 的解决方案。

如果您需要一个很好的可下载示例解决方案来演示使用侧边菜单的导航,请查看here 和here(simpler example)。

【讨论】:

以上是关于在 MVVM WPF 应用程序中处理导航的主要内容,如果未能解决你的问题,请参考以下文章

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

WPF MVVM:MainWindow导航

如何在 MVVM 模式中从页面导航到 WPF 中的页面?没有棱镜的概念[重复]

WPF、MVVM、导航、保持依赖注入完整

在 WPF MVVM 中的视图之间导航

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