Passing complex navigation parameters with MvvmCross ShowViewModel

戏子无情 提交于 2019-11-27 04:32:04

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

A small addition to Stuart's answer to add type safety:

public class BaseViewModel: MvxViewModel {

    protected bool ShowViewModel<TViewModel, TInit>(TInit parameter) where TViewModel: BaseViewModel<TInit> {
        var text = Mvx.Resolve<IMvxJsonConverter>().SerializeObject(parameter);
        return base.ShowViewModel<TViewModel>(new Dictionary<string, string> { {"parameter", text} });
    }
}

public abstract class BaseViewModel<TInit> : BaseViewModel {

    public void Init(string parameter)
    {
        var deserialized = Mvx.Resolve<IMvxJsonConverter>().DeserializeObject<TInit>(parameter);
        RealInit(deserialized);
    }

    protected abstract void RealInit(TInit parameter);
}

ShowViewModel method now takes the same parameter type that the RealInit method instead of an object type. Also, BaseViewModel<TInit> inherits from BaseViewModel so their instances can also call the new ShowViewModel method.

The only drawback is that you have to explicitly specify the parameter type in the call like this:

ShowViewModel<StoreInfoViewModel, Store>(store);
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!