在不同的MvvmCross (v3)平台上处理GoBack的最佳方式是什么?

本文关键字:GoBack 处理 最佳 方式 是什么 MvvmCross v3 平台 | 更新日期: 2023-09-27 18:10:27

在MvvmCross v3中,我使用ShowViewModel导航到不同的页面。在转换到Mvx之前,我会使用NavigationService.GoBack()方法返回到上一页。优点是不需要重新创建页面。

由于GoBack方法是平台特定于WP, WInRT, Silverlight,什么是最好的方式来处理返回到上一页,使视图模型保持平台独立?

一个解决方案可能是使用ShowViewModel传递视图可以看到的一些数据,然后在WP/WinRT的情况下,从视图调用RemoveBackEntry。但是对于Mvx,可能有更好的方法。

在不同的MvvmCross (v3)平台上处理GoBack的最佳方式是什么?

在MvvmCross v3中,我们提供了一种特定的机制,允许ViewModels向UI发送他们想要更改当前表示的消息。

这个机制就是ChangePresentation(MvxPresentationHint hint),它提供了从ViewModelsPresenter的消息路由——表示提示。

Presenter如何处理这些消息是平台和应用程序特定的。

这个消息机制是非常通用的,它可能在未来被用于各种各样的事情——例如,开发人员可能会提供提示来做一些事情,比如改变UI布局,突出UI的一部分,迫使用户关注某个控件,导致SIP显示或隐藏,等等。


对于关闭视图模型的情况,我们提供了MvxPresentationHint - MvxClosePresentationHint的专门化和MvxViewModel基类中的辅助方法:

    protected bool Close(IMvxViewModel viewModel)
    {
        return ChangePresentation(new MvxClosePresentationHint(viewModel));
    }

使用这个ViewModel可以调用Close(this)

当它被调用时,UI中的Presenter将收到一条关于ChangePresentation方法的消息:

public interface IMvxViewPresenter
{
    void Show(MvxViewModelRequest request);
    void ChangePresentation(MvxPresentationHint hint);
}

对于一般/典型的情况-其中ViewModel被关闭附加到视图是最上面的Activity/Page/UIViewController, MvvmCross中的默认呈现者将能够处理此消息,并将能够在Windows中GoBack,在Android中Finish,在iOS中PopViewController

然而,如果你的UI比这更复杂-例如,如果ViewModel你想要Close实际上对应于Tab, Flyout, SplitView窗格,等等,或者如果ViewModel对应于当前层次结构中最顶层的视图以外的东西-那么你将需要提供一个自定义的演示器实现-并且该实现将不得不做平台和应用程序特定的逻辑来处理Close


上面的提示是我建议你使用的…

但是,作为的替代:

如果你觉得这个ChangePresentation(MvxPresentationHint hint)机制对你的应用来说太重量级了,那么你当然也可以选择一个自定义的或基于Message的机制。

这样做的一个示例是CustomerManagement示例-它在每个平台上提供了自定义IViewModelCloser实现-参见:

  • 自定义界面- https://github.com/slodge/MvvmCross/blob/v3/Sample%20-%20CustomerManagement/CustomerManagement/CustomerManagement/Interfaces/IViewModelCloser.cs
  • BaseViewModel - https://github.com/slodge/MvvmCross/blob/v3/Sample%20-%20CustomerManagement/CustomerManagement/CustomerManagement/ViewModels/BaseViewModel.cs
  • Droid - https://github.com/slodge/MvvmCross/blob/v3/Sample%20-%20CustomerManagement/CustomerManagement/CustomerManagement.Droid/SimpleDroidViewModelCloser.cs
  • WP - https://github.com/slodge/MvvmCross/blob/v3/Sample%20-%20CustomerManagement/CustomerManagement/CustomerManagement.WindowsPhone/ViewModelCloser.cs
  • Touch - https://github.com/slodge/MvvmCross/blob/v3/Sample%20-%20CustomerManagement/CustomerManagement/CustomerManagement.Touch/CustomerManagementPresenter.cs

我不完全确定mvvmcross,但在MVVM Light中通常做的是创建一个INavigationService接口来暴露这些方法。

然后,每个平台以特定于平台的方式实现该接口(例如在WP中,通过获取对当前框架及其内容的引用)。然后,这个平台特定的实例可以执行所有正确的操作,以确保正确实现导航模式。

你的ViewModels可以通过依赖容器获得对INavigationService实例的引用。这样你的VM就独立于导航的平台细节。

我还写了一篇关于如何使用接口为平台特定功能公开公共API的博客文章:http://www.kenneth-truyers.net/2013/02/24/patterns-for-sharing-code-in-windows-phone-and-windows-8-applications/

博客文章中的例子是关于隔离存储的,但同样的原则也适用于导航(或任何在不同平台上有不同实现的功能)