v3中导航参数中的自定义类型

Der*_*tie 5 mvvmcross

在v3中,如果我想将两个对象传递给另一个viewmodel:

public class Dog
{

}

public class Cat
{

}

var dog = new Dog();
var cat = new Cat();

ShowViewModel<SomeViewModel>(new {Dog = dog, Cat = cat });

public class SomeViewModel
{
  Init(Dog dog, Cat cat)
  {
  }
}
Run Code Online (Sandbox Code Playgroud)

据我所知,这是行不通的,因为类型不被识别,不能卡在字典中.如果我希望将这些序列化为json,传递给视图模型,并反序列化为Init参数,我会实现IExtraParser吗?如果这是正确的,我该如何将实现添加到ExtraParsers字典?

更新:

这似乎是这样做的:

var foo = Mvx.Resolve<IMvxFillableStringToTypeParser>();
foo.ExtraParsers.Add(new MyParser());
Run Code Online (Sandbox Code Playgroud)

Stu*_*art 11

MvvmCross中的默认导航机制是故意轻量级的.

它实际上只允许您传递一个简单的,可序列化的对象 - 例如

public class DogNav
{
   public int Id {get;set;}
   public string Caption {get;set;}
}

// received in:
public class DogViewModel : MvxViewModel
{
   public void Init(DogNav dogNav)
   {
   }
}
Run Code Online (Sandbox Code Playgroud)

使用此设置,如果触发导航,如:

// navigation
ShowViewModel<DogViewModel>(new DogNav() { Id=12, Caption="Good boy" });
Run Code Online (Sandbox Code Playgroud)

那么底层系统将输送的值从该DogNav对象-可能使用UriS,Intents或其它串行技术-到新的DogViewModel,然后将确保Init被调用正确的值.

由于序列化,重要的是:

  • 传递大对象(UriWindowsPhone上的s可以突破几百个字符)
  • 期待获得同样的对象实例到达-如果你正在使用的数据库支持或状态的对象,即,那么最好通过某种查找键,而不是对象本身.
  • 不要指望只有一个ViewModel会收到消息 - 在某些操作系统上,可能是用户在应用程序之间来回多次,导致创建了许多视图和ViewModel.
  • 不要指望接收消息的ViewModel与发送请求的ViewModel位于相同的进程和内存空间中 - 实际上可能会在逻辑删除事件发生后几天收到.

如果您确实想通过导航传递多个对象,那么我认为您可以使用以下代码执行此操作:

public class CatNav
{
   public int CatId {get;set;}
   public string CatCaption {get;set;}
}

public class DogNav
{
   public int DogId {get;set;}
   public string DogCaption {get;set;}
}

// received in:
public class CatAndDogViewModel : MvxViewModel
{
   public void Init(DogNav dogNav)
   {
   }

   public void Init(CatNav catNav)
   {
   }
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,您可以使用:

var catNav = new CatNav() { CatId =12, CatCaption="Meow" };
var dogNav = new DogNav() { DogId =12, DogCaption="Woof" };
var bundle = new MvxBundle();
bundle.Write(catNav);
bundle.Write(dogNav);
ShowViewModel<CatAndDogViewModel>(bundle);
Run Code Online (Sandbox Code Playgroud)

我认为这会奏效......

但是......请注意序列化非常简单 - 所以如果CatNavDogNav共享一个属性名称,那么这会导致问题 - 你最终会得到一些Cags and Dots

由于Cag和Dot问题,我不推荐这种方法......


如果您确实需要在应用中进行更复杂的转换,那么一条路线就是:

更新 - 请参阅使用MvvmCross ShowViewModel传递复杂的导航参数

1.添加Json插件(或任何Json序列化程序)并更改您的Setup.cs代码以创建MvxJsonNavigationSerializer - 覆盖CreateNavigationSerializer

     protected override IMvxNavigationSerializer CreateNavigationSerializer()
     {
         return new MvxJsonNavigationSerializer();
     }
Run Code Online (Sandbox Code Playgroud)
  1. 在导航中使用复合对象,如:

    public class DogAndCatNav
    {
       public DogNav DogNav {get;set;}
       public CatNav CatNav {get;set;}
    }
    
    Run Code Online (Sandbox Code Playgroud)
  2. 这将通过以下方式收到:

    public void Init(DogAndCatNav dogAndCatNav)
    {
    }
    
    Run Code Online (Sandbox Code Playgroud)

但请注意,这种技术确实需要更强大的序列化引擎 - 例如Json.


整体而言...即使写完了所有这些...... 我建议你在导航中传递尽可能少的数据!