MvvmCross和复杂的导航

时间:2014-03-03 08:42:42

标签: navigation xamarin mvvmcross

我很难理解,mvvmcross导航如何在一些更复杂的情况下工作。让我们来看看我们想要使用mvvmcross作为基础的WP7和Metro。我们创建三个视图模型( FirstViewModel,SecondViewModel,ThirdVIewModel ),用一些数据填充它们并使用常规导航在它们之间移动(使用 ShowViewModel()方法)。到目前为止,这种方法运行良好,我们希望在Windows Phone设备上实现这种导航,这是三个独立的视图,我们可以来回导航。

现在从Metro应用程序的角度来看 - 我们有更大的屏幕,通常用于lanscape模式,因此我们决定将这三个页面的内容显示为单个页面。

这是我看到问题的地方 - 因为两个版本的应用程序都使用相同的Core和相同的视图模型层次结构 - 似乎不可能同时拥有这种行为。从FirstViewModel到SecondViewModel的导航不适用于Metro版本的应用程序,因为我们实际上在第一个屏幕上,我们想要包含来自所有三个视图模型的所有数据。另一方面 - 我们不能将这三个视图模型放在较大的模型中并将其用作单视图模型,因为这三个独立的视图模型以及常规导航在Windows Phone上对我们来说效果很好。

有没有办法使用mvvmcross提供这种非标准导航?如果是这样,是否需要覆盖/添加一些简单的代码(我看不到,可能?),或者相当复杂的东西,需要大量的时间和编码才能实现这种功能?

2 个答案:

答案 0 :(得分:2)

MvvmCross有不同的方法来改变它的默认机制。 一个好的起点是Wiki:https://github.com/MvvmCross/MvvmCross/wiki/Customising-using-App-and-Setup

关于您的示例:

我的一个想法是创建一个MainViewModel,它包含WindowStore应用程序的所有三个视图模型。

即使它仅由Windows应用商店应用使用,您仍然可以在Core项目中安装MainViewModel。您可能希望稍后将其用于Android或iOS平板电脑应用程序:

public class MainViewModel : MvxViewModel
{
    public FirstViewModel First { get; private set; }
    public SecondViewModel Second { get; private set; }
    public ThirdViewModel Third { get; private set; }

    public MainViewModel()
    {
          this.First = new FirstViewModel();
          this.Second = new SecondViewModel();
          this.Third = new ThirdViewModel();
     }
}

接下来,根据平台,您需要导航到MainViewModel或FirstViewModel

在MvvmCross中,有几种方法可以做到这一点。

一个选项是使用CustomAppStart,根据平台导航到初始视图模型。

在核心库中:

 public class CustomAppStart
        : MvxNavigatingObject
        , IMvxAppStart
    {
        public void Start(object hint = null)
        {
           var platform == GetRunningPlatform();
           switch(platform)
           { 
              case Platform.WinStore:
                   ShowViewModel<MainViewModel>();
                   break;
              case Platform.WinPhone:
                   ShowViewModel<FirstViewModel>();
                   break;               
              ...    
        }
    }

为了检测应用程序正在运行的平台,还有很少的方法可以执行此操作。 检查How can I detect the platform at runtime using MvvMCross?或MvvmLight如何执行此操作:http://mvvmlight.codeplex.com/SourceControl/network/forks/onovotny/MvvmLightPortable/changeset/view/f356af74426f#GalaSoft.MvvmLight/Portable/GalaSoft.MvvmLight/Helpers/DesignerPlatformLibrary.cs

另一个想法是在每个平台上都有单独的WinPhoneAppStart和WinStoreAppStart。请注意,在创建IMvxApplication之前,需要注册自定义应用程序启动(IMvxAppStart)。

在Windows应用商店应用中:

public class WinStoreAppStart : MvxNavigatingObject, IMvxAppStart
{
    public void Start(object hint = null)
    {
       ShowViewModel<MainViewModel>();   
    }  
}

public class Setup : MvxStoreSetup
{ 
     protected override IMvxApplication CreateApp()
     {
         Mvx.RegisterType(typeof(IMvxAppStart), typeof(WinStoreAppStart));
         return new Core.App();
     } 
}
p,我希望这可以帮到你。如果您需要更多信息,请告诉我。

修改

如果3个页面不代表起始主页,那么我的一个想法是使用自定义演示者:https://github.com/MvvmCross/MvvmCross/wiki/Customising-using-App-and-Setup#wiki-custom-presenters

在WinStore应用程序中,您可以捕获导航到FirstViewModel,而是创建MainViewModel。

另一个想法:

您可以拥有一个实现视图模型导航的平台相关控制器。

答案 1 :(得分:1)

是的,虽然您需要编写一些自定义类。如果您为每个平台编写自定义演示者,则可以使用区域的概念,其中您的视图可以指示他们希望显示的区域,以便在调用ShowViewModel时,您的自定义演示者可以检查相应视图是否请求特定区域并在必要时处理。

在自定义演示者上查看Stuart Lodges n + 1。还有谷歌“MVVMCross区域主持人”。你应该找到一些有用的材料。

干杯, 特里斯坦