Custom types in Navigation parameters in v3

前端 未结 1 1739
粉色の甜心
粉色の甜心 2020-12-10 07:47

In v3 if I wanted to pass two objects to another viewmodel:

public class Dog
{

}

public class Cat
{

}

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

ShowView         


        
相关标签:
1条回答
  • 2020-12-10 08:39

    The default navigation mechanism in MvvmCross is deliberately lightweight.

    It is really there to allow you to pass just one simple, serializable object - e.g.

    public class DogNav
    {
       public int Id {get;set;}
       public string Caption {get;set;}
    }
    
    // received in:
    public class DogViewModel : MvxViewModel
    {
       public void Init(DogNav dogNav)
       {
       }
    }
    

    With this setup, if a navigation is triggered like:

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

    then the underlying system will transport the values from that DogNav object - possibly using Uris, Intents or other serialization techniques - to the new DogViewModel and will then ensure Init is called with the correct values.

    Because of the serialization, it's important:

    • not to pass big objects (Uris on WindowsPhone can break above a few hundred characters)
    • not to expect the same object instance to arrive - i.e. if you are using database-backed or stateful objects, then it's best to pass some kind of lookup key rather than the objects themselves.
    • not to expect that only one ViewModel will receive the message - on some operating systems, it may be that the user goes back and forth many, many times between apps causing many Views and ViewModels to be created.
    • not to expect that a ViewModel that receives the message is in the same process and memory space as the ViewModel that sent the request - the same may actually be received days later after a tombstoning event.

    If you do want to pass multiple objects via navigation, then I think you can do this using code like:

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

    In this case you could navigate using:

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

    I think this would work...

    However... please be aware that the serialization is very simple - so if CatNav and DogNav were to share a property name, then this would lead to problems - you'd end up with some Cags and Dots

    Because of the Cag and Dot problem I don't recommend this approach...


    If you do need more complex transitions in your apps, then one route is to:

    UPDATE - see Passing complex navigation parameters with MvvmCross ShowViewModel

    1. Add the Json Plugin (or any Json serializer) and change your Setup.cs code to create a MvxJsonNavigationSerializer - overriding CreateNavigationSerializer

         protected override IMvxNavigationSerializer CreateNavigationSerializer()
         {
             return new MvxJsonNavigationSerializer();
         }
    
    1. Use a composite object in navigation like:

      public class DogAndCatNav
      {
         public DogNav DogNav {get;set;}
         public CatNav CatNav {get;set;}
      }
      
    2. This would be received by:

      public void Init(DogAndCatNav dogAndCatNav)
      {
      }
      

    But note that this technique does need a more powerful serialization engine - such as Json.


    Overall... even after writing all this... I'd recommend you pass as little data as possible in your navigations!

    0 讨论(0)
提交回复
热议问题