Search code examples
serializationnavigationviewmodelmvvmcrosscomplextype

Passing complex navigation parameters with MvvmCross ShowViewModel


My complex type wouldn't pass from Show to Init method even with configured MvxJsonNavigationSerializer as specified here Custom types in Navigation parameters in v3

public class A
{
 public string String1 {get;set;}
 public string String2 {get;set;}
 public B ComplexObject1 {get;set;}
}

public class B
{
 public double Double1 {get;set;}
 public double Double2 {get;set;}
}

When I pass instance of object A to ShowViewModel method I receive this object with String1 & String2 deserialized correctly but CopmlexObject1 is null.

How to deal with complex object MvvmCross serialization?


Solution

  • I believe there may be some gremlins in that previous answer - will log as an issue :/


    There are other possible routes to achieve this type of complex serializable object navigation still using Json and overriding parts of the framework, but actually I think that it might be better to just use your own BaseViewModel's to do serialization and deserialization - e.g. use serialization code like:

    public class BaseViewModel
        : MvxViewModel
    {
        private const string ParameterName = "parameter";
    
        protected void ShowViewModel<TViewModel>(object parameter)
            where TViewModel : IMvxViewModel
        {
            var text = Mvx.Resolve<IMvxJsonConverter>().SerializeObject(parameter);
            base.ShowViewModel<TViewModel>(new Dictionary<string, string>()
                {
                    {ParameterName, text}
                });
        }
    }
    

    with deserialization like:

    public abstract class BaseViewModel<TInit>
        : MvxViewModel
    {
        public void Init(string parameter)
        {
            var deserialized = Mvx.Resolve<IMvxJsonConverter>().DeserializeObject<TInit>(parameter);
            RealInit(deserialized);
        }
    
        protected abstract void RealInit(TInit parameter);
    }
    

    then a viewModel like this:

    public class FirstViewModel
        : BaseViewModel
    {
        public IMvxCommand Go
        {
            get
            {
                return new MvxCommand(() =>
                    {
                        var parameter = new A()
                            {
                                String1 = "Hello",
                                String2 = "World",
                                ComplexObject = new B()
                                    {
                                        Double1 = 42.0,
                                        Double2 = -1
                                    }
                            };
                        ShowViewModel<SecondViewModel>(parameter);
                    });
            }
        }
    }
    

    can navigate to something like:

    public class SecondViewModel
        : BaseViewModel<A>
    {
        public A A { get; set; }
    
        protected override void RealInit(A parameter)
        {
            A = parameter;
        }
    }