如何在不同的MvvmCross(v3)平台上处理GoBack最佳方法

13
在 MvvmCross v3 中,我使用 ShowViewModel 进行页面导航。在转换到 Mvx 之前,我会使用 NavigationService.GoBack() 方法返回上一页,这样可以避免重新创建页面。
由于 GoBack 方法是特定于 WP、WinRT、Silverlight 平台的,因此如何返回上一页并使视图模型保持平台无关性呢?
一种解决方案可能是使用 ShowViewModel 传递一些数据给视图,并在 WP/WinRT 的情况下从视图中调用 RemoveBackEntry。但是,在 Mvx 中,可能有更好的方法。
2个回答

18
在MvvmCross v3中,我们提供了一种特定机制,允许ViewModel发送消息到UI,以便更改当前呈现内容。这个机制是ChangePresentation(MvxPresentationHint hint),它提供了从ViewModels到Presenter的消息路由-呈现提示。Presenter如何处理这些消息取决于平台和应用程序特定。该消息机制非常通用,未来可能用于各种情况-例如,开发人员可以提供提示来更改UI布局、突出显示UI的某些部分、强制用户关注某个控件、导致SIP显示或隐藏等。对于关闭视图模型的情况,我们提供了MvxClosePresentationHintMvxPresentationHint特化版本,并在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中的默认Presenter可以处理此消息,并能够在Windows中返回 (GoBack),在Android中结束 (Finish),在iOS中弹出视图控制器 (PopViewController)。

但是,如果你的UI比这更复杂——例如,如果你想要关闭的ViewModel实际上对应于一个Tab、一个Flyout、一个SplitView面板等,或者如果ViewModel对应于层次结构中除了当前最上层视图之外的其他内容,则需要提供自定义的Presenter实现,并且该实现将需要执行特定于平台和应用程序的逻辑以处理Close操作。


以上提示是我建议您使用的...

但是,作为替代方案

如果您认为ChangePresentation(MvxPresentationHint hint)机制过于繁重/过度,当然也可以改用自定义或基于Message的机制。

其中一个示例是CustomerManagement样例——它为每个平台提供了自定义的IViewModelCloser实现——请参见:


我看到并喜欢你说可以从一个平台的Presenter继承,覆盖ChangePresenter,并告诉Mvx使用新的Presenter。 - Derek Beattie

3
我不完全确定mvvmcross,但在MVVM Light中通常的做法是创建一个INavigationService接口来公开这些方法。
然后,每个平台以特定于该平台的方式实现此接口(例如,在WP中通过获取对当前帧及其内容的引用)。这个特定于平台的实例可以执行所有正确的操作,以确保正确实现导航模式。
您的ViewModel可以通过依赖容器获得INavigationService实例的引用。这样,您的VM就不会受到导航平台特定性的影响。
我还写了一篇关于如何使用接口来公开平台特定功能的通用API的博客文章:http://www.kenneth-truyers.net/2013/02/24/patterns-for-sharing-code-in-windows-phone-and-windows-8-applications/ 博客文章中的示例是关于独立存储,但同样的原理适用于导航(或任何具有不同平台实现的功能)。

2
好的观点,但 Mvx 使得所有平台的视图模型都存储在可移植类库中。因此,导航被抽象化,并由 MvxNavigatingObject 中的 ShowViewModel 实现。如果出现某些平台不支持 GoBack 等功能的情况,它并不存储在 Mvx 的核心中。 - Derek Beattie
好的,我不知道那个。就像我说的,我没有使用过MVVMcross,所以也许我的观点在你的情况下无效。然而,继承mvxNavigationObject并添加该方法(当然是抽象的)是否是一种解决方案?这只是一个猜测,也许根本没有意义。 - Kenneth
已经添加了一个答案 - @Kenneth的一般观点非常准确(所以我给他+1)。我的回答只是为了提供我们如何在MvvmCross中使用ChangePresentation API来提供这种抽象的具体细节。除了提供这个API之外,我们还提供了针对诸如FileStorage之类的插件 :) - Stuart

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接