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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15426082/
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-13 08:05:38  来源:igfitidea点击:

Handling Navigation in MVVM WPF application

c#wpfmvvm

提问by Anirban Paul

I am developing a WPF application that follows MVVM. Now I am handling navigation of views in the following manner. MainWindow View

我正在开发一个遵循 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 are 3 views. HomeVM,Page1VM,Page2VM are view models corresponding to the views. There is a class call ApplicationViewModel that contains a property CurrentView of type CViewModelBase which is the parent class for all three viewmodels. ApplicationViewModel handles the navigation in the folowing manner

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);
    }

The navigation is working perfectly; But dispose of disappeared views are not getting called.So all the views live till the end. Is there any way to prevent that?

导航工作正常;但是处理消失的视图并没有被调用。所以所有的视图都存在到最后。有什么办法可以防止吗?

回答by Rachel

Your Views will always exist because you added a copy of each one to your UI with the XAML, even if the Contentcontained in them may not exist

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

Typically I will use a ContentControlto display content instead of creating an instance of the control for each content type, and I'll use DataTemplatesto tell WPF how to draw each type of content.

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

For example,

例如,

<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>

This way, you only have one instance of your Contentin the VisualTree, and the DataTemplateWPF users to draw your content changes based on it's DataType.

这样,您Content在 VisualTree 中只有一个您的实例,DataTemplateWPF 用户可以根据它的DataType.

I have an example of this kind of navigation with WPFon my blog if you're interested in checking out a full code sample

如果您有兴趣查看完整的代码示例,我的博客上有一个使用 WPF进行导航的示例

回答by fhnaseer

You need to change DataContext of MainWindow. It depends on your integration. When I make a MVVM application what I do is that pass MainWindow object to every view constructor. And whenever I have to move to next page (like on next button) I change the MainWindow object DataContext to new view.

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

Something like this.

像这样的东西。

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);
    }
}

回答by David

Have you considered using Frame?

你考虑过使用Frame吗?

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

and then you can call

然后你可以打电话

YourFrame.CanGoBack(), YourFrame.GoBack()

YourFrame.CanGoBack(), YourFrame.GoBack()

etc.

等等。

回答by failedprogramming

Here's a linkto my answer to a similar question with working source code. The technique I used is a little similar to Faisal's solution.

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

If you need a good downloadable sample solution that demonstrates navigation using a side menu, look at hereand here(simpler example).

如果您需要一个很好的可下载示例解决方案来演示使用侧边菜单的导航,请查看此处此处(更简单的示例)