在mvvmcross中的视图模型之间传递多态类型

时间:2015-05-15 15:24:55

标签: c# android xamarin mvvmcross

我有两个按钮,两个按钮都显示一个新的视图模型,但是传递给viewmodel的数据不同。传递的数据并不完全不同,因此它们都从相同的基础继承。不幸的是,似乎传递给viewmodel的Init()方法的数据在途中丢失了它的运行时类型信息?使用调试器(或代码),传递的数据被识别为基类 - 而不是实际构造并传递给ShowViewModel<>()方法的派生类。

我试图做的不可能吗?

public class BasePasser
{

}

public class PasserA : BasePasser
{

}

public class PasserB : BasePasser
{

}


public class ViewModelOne : MvxViewModel
{
    // ...
    private void DoSwitchViewModelA()
    {
        var tobepassed = new PasserA {
            // ...
            };

        ShowViewModel<ViewModelTwo>(tobepassed);
    }

    private void DoSwitchViewModelB()
    {
        var tobepassed = new PasserB {
            // ...
            };

        ShowViewModel<ViewModelTwo>(tobepassed);
    }
}

public class ViewModelTwo : MvxViewModel
{
    // ...
    public async Task Init(BasePasser passed)
    {
        if(passed is PasserA)
        {
            // ...
        }
        else if(passed is PasserB)
        {
            // ...
        }
        else
        {
            // Always called/hit
            throw new InvalidOperationException("Unknown data passed");
        }
    }
}

1 个答案:

答案 0 :(得分:5)

在MvvmCross中显示ViewModel实际上是一个非常复杂的过程。

当您调用 ShowViewModel(param)时,Mvx会将param值序列化为名称/值字典。此时,param的Type信息将丢失。

实例化ViewModel后,它最终将查找ViewModel上定义的任何 Init 方法。

如果您查看 Cirrious.MvvmCross.ViewModels.MvxViewModelExtensions.CallBundleMethod(),您会看到它首先查找具有IMvxBundle类型的单个参数的方法。然后它查找一个不是简单类型的单个参数(如string,int等)

如果找到此类型,则假定它是在ShowViewModel()调用中已序列化的对象。然后,它尝试根据Init方法中的参数类型而不是原始类型反序列化值。

这就是为什么你只看到基类型,因为Mvx没有初始调用的类型信息,并且在反序列化时,只能从Init方法中看到基类型。

解决方法是将所有属性放入单个类中。只设置你需要的那个,并创建一个discriminator属性,指定哪个&#34; type&#34;它是。

var param = new Passer { PasserType = "A", ParamA = "ValueA", ... etc. }

您还可以选择使用命名方法参数。

请参阅https://github.com/MvvmCross/MvvmCross/wiki/View-Model-Lifecycle

中的 Init 部分