使用MvvmCross ShowViewModel传递复杂的导航参数

15

即使按照在v3中导航参数中的自定义类型所述配置了MvxJsonNavigationSerializer,我的复杂类型仍无法从Show方法传递到Init方法。

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

当我将对象A的实例传递给ShowViewModel方法时,我会收到一个包含String1和String2正确反序列化的对象,但ComplexObject1为null。

如何处理MvvmCross序列化中的复杂对象?


我通过在我的uiview项目中添加mvvmcross json插件来解决了这个问题。 - Nilay Patel
2个回答

26

我认为之前的回答可能有些错误 - 我会将其记录为一个问题 :/


还有其他可能的方法来实现这种复杂可序列化对象导航,仍然使用 Json 并覆盖框架的某些部分,但实际上我认为最好的方法是使用自己的 BaseViewModel 来进行序列化和反序列化——例如使用以下序列化代码:

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

使用反序列化技术,例如:

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

那么一个像这样的viewModel:

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

可以导航到类似以下内容:
public class SecondViewModel
    : BaseViewModel<A>
{
    public A A { get; set; }

    protected override void RealInit(A parameter)
    {
        A = parameter;
    }
}

谢谢!有趣的方法,这绝对可行,因为我完全可以自己控制序列化/反序列化过程。 - Mando

10

在 Stuart 的答案中,为了增加类型安全性,有一个小的补充:

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方法现在采用与RealInit方法相同的参数类型,而不是object类型。另外,BaseViewModel<TInit>继承自BaseViewModel,因此它们的实例也可以调用新的ShowViewModel方法。

唯一的缺点是你必须在调用时明确指定参数类型,就像这样:

ShowViewModel<StoreInfoViewModel, Store>(store);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接