8

我一直在跨平台移动项目上使用 MvvmCross,并且在 MonoTouch 项目中有两个不同的视图,它们使用相同的共享视图模型,并且不知道如何构建我的代码以使用 MvvmCross 中的相同视图模型导航到不同的视图。

4

3 回答 3

12

MvvmCross 平台使用的默认约定是使用反射自动注册所有视图。

这是在基本 Setup 类中完成的 - 在https://github.com/slodge/MvvmCross/blob/master/Cirrious/Cirrious.MvvmCross/Platform/MvxBaseSetup.cs中:

    protected virtual void InitializeViews()
    {
        var container = this.GetService<IMvxViewsContainer>();

        foreach (var pair in GetViewModelViewLookup())
        {
            Add(container, pair.Key, pair.Value);
        }
    }

whereGetViewModelViewLookup将 ViewModel 类型的字典返回到 View 类型:

    protected virtual IDictionary<Type, Type> GetViewModelViewLookup(Assembly assembly, Type expectedInterfaceType)
    {
        var views = from type in assembly.GetTypes()
                    let viewModelType = GetViewModelTypeMappingIfPresent(type, expectedInterfaceType)
                    where viewModelType != null
                    select new { type, viewModelType };

        return views.ToDictionary(x => x.viewModelType, x => x.type);
    }

在通用 iPad/iPhone 应用程序中,您有时确实希望为每个视图模型包含多个视图 - 在 iPad 中使用一个视图,在 iPhone 中使用一个视图。

要做到这一点,现在(字面意思就是现在!)一些属性可用于将您的视图标记为“非常规” - 这些是:

在这种情况下,最后一个可能是您想要的 - 您可以使用声明如下的两个视图为 MainViewModel 实现简单的 iPhone/iPad 切换:

[MvxFormFactorSpecificView(MvxTouchFormFactor.Phone)]
public class MyIPhoneView : BaseView<MainViewModel>
{
    // iphone specific view ...
}

[MvxFormFactorSpecificView(MvxTouchFormFactor.Pad)]
public class MyIPadView : BaseView<MainViewModel>
{
    // ipad specific view ...
}

或者,如果您想要一个非常自定义的配置,您可以覆盖所有“基于约定”的行为 - 您可以实现自己的覆盖GetViewModelViewLookup- 例如:

protected override IDictionary<Type, Type> GetViewModelViewLookup(Assembly assembly, Type expectedInterfaceType)
{
    if (IsIPad)
    {
        return new Dictionary<Type, Type>() 
        {
            { typeof(HomeViewModel), typeof(IPadHomeView) },
            { typeof(DetailViewModel), typeof(IPadDetailView) },
            { typeof(AboutViewModel), typeof(SharedAboutView) },
        };
    }
    else
    {
        return new Dictionary<Type, Type>() 
        {
            { typeof(HomeViewModel), typeof(IPhoneHomeView) },
            { typeof(DetailViewModel), typeof(IPhoneDetailView) },
            { typeof(AboutViewModel), typeof(SharedAboutView) },
        };
    }
}

请注意,最终您可能会决定您需要额外的 ViewModel 以及 iPad 应用程序的视图 - 毕竟 iPad 具有更大的屏幕 - 在这种情况下,您可以手动添加它们。最终,当您的应用程序达到几百万用户时,您甚至可能决定将平板电脑代码完全从手机代码中分离出来 - 但这通常可以等到您达到几百万大关......

于 2012-04-24T12:31:12.020 回答
0

另一种方法是继续创建 2 个 ViewModel,但让它们都成为抽象 ViewModel 的子类,如下所示:

FirstViewViewModel : BaseViewModel
SecondViewViewModel : BaseViewModel

对应的视图命名为:

FirstView.xaml
SecondView.xaml

这样,您可以在BaseViewModel中放置一些共享行为,而这两个子类实际上只是为了满足 MvvmCross 的视图获取约定。

于 2015-08-06T19:14:54.307 回答
0

我最近开始使用 MvvmCross,我使用的是 v4.2.1。好像有些名字变了。我正在使用一个带有单独 iPhone 和 iPad 视图的 ViewModel,其中包含以下内容:

[MvxFormFactorSpecific(MvxIosFormFactor.Phone)]
public class MyIPhoneView : BaseView<MainViewModel>
{
    // iphone specific view ...
}

[MvxFormFactorSpecific(MvxIosFormFactor.TallPhone)]
public class MyTallIPhoneView : BaseView<MainViewModel>
{
    // tall iphone specific view ...
}

[MvxFormFactorSpecific(MvxIosFormFactor.Pad)]
public class MyIPadView : BaseView<MainViewModel>
{
    // ipad specific view ...
}
于 2016-07-08T11:36:57.427 回答