单个ViewModel(iOS)的多个视图

时间:2015-02-17 23:08:29

标签: ios xamarin.ios xamarin xamarin.android mvvmcross

我知道为了实现这一点,我需要创建一个自定义演示者,并通过覆盖InitializeViewLookup方法手动将ViewModel映射到我的视图。我在Android上成功做到了这一点,到目前为止一切正常,但我似乎无法在iOS上做到这一点。这就是我的尝试:

public override void Show(MvxViewModelRequest request)
    {
        // check if there are any presentation values
        if (request.PresentationValues != null)
        {
            // if yes, check if one of them is SelectedView
            if (request.PresentationValues.ContainsKey(SingletonViewModelLocator.SelectedView))
            {
                UIViewController viewController;
                switch (request.PresentationValues[SingletonViewModelLocator.SelectedView])
                {
                    // The ViewModel requested the First View, load that one
                    case SingletonViewModelLocator.FirstViewValue:
                        viewController = new FirstView();
                        MasterNavigationController.PushViewController(viewController, true);
                        return;
                    // The ViewModel requested the Second View, load that one
                    case SingletonViewModelLocator.SecondViewValue:
                        viewController = new SecondView();
                        MasterNavigationController.PushViewController(viewController, true);
                        return;
                    // wrong view requested
                    default:
                        throw (new InvalidEnumArgumentException(request.PresentationValues[SingletonViewModelLocator.SelectedView] +
                                                                " does not exist."));
                }
            }
        }
        // otherwise run the default method which means 1 ViewModel is mapped to 1 View
        base.Show(request);
    }

此处InitializeViewLookup

protected override void InitializeViewLookup()
    {
        var container = Mvx.Resolve<IMvxViewsContainer>();
        container.Add(typeof(MainViewModel), typeof(MainView));
        // TheViewModel is mapped to two Views
        container.Add(typeof(TheViewModel), typeof(FirstView));
        container.Add(typeof(TheViewModel), typeof(SecondView));
    }

这使得&#34;对象引用未设置为对象的实例&#34;导航发生时,ViewDidLoad方法上Mvx库内部的异常。

仅供参考,以下是我在 Android 上进行操作的原因。

public override void Show(MvxViewModelRequest request)
    {
        // check if there are any presentation values
        if (request.PresentationValues != null)
        {
            // if yes, check if one of them is SelectedView
            if (request.PresentationValues.ContainsKey(SingletonViewModelLocator.SelectedView))
            {
                var activity = Activity;
                Intent intent;
                switch (request.PresentationValues[SingletonViewModelLocator.SelectedView])
                {
                    // The ViewModel requested the First View, load that one
                    case SingletonViewModelLocator.FirstViewValue:
                        intent = new Intent(activity, typeof (FirstView));
                        Show(intent);
                        return;
                    // The ViewModel requested the Second View, load that one
                    case SingletonViewModelLocator.SecondViewValue:
                        intent = new Intent(activity, typeof (SecondView));
                        Show(intent);
                        return;
                    // wrong view requested
                    default:
                        throw (new InvalidEnumArgumentException(request.PresentationValues[SingletonViewModelLocator.SelectedView] +
                                                                " does not exist."));
                }
            }
        }
        // otherwise run the default method which means 1 ViewModel is mapped to 1 View
        base.Show(request);
    }

修改

这是堆栈跟踪:

0x0 in Cirrious.MvvmCross.ViewModels.MvxViewModelLoader.LoadViewModel   
0x65 in Cirrious.MvvmCross.Touch.Views.MvxViewControllerExtensionMethods.LoadViewModel  
0x13 in Cirrious.MvvmCross.Views.MvxViewExtensionMethods.OnViewCreate   
0xE in Cirrious.MvvmCross.Touch.Views.MvxViewControllerExtensionMethods.OnViewCreate    
0x7 in Cirrious.MvvmCross.Touch.Views.MvxViewControllerAdapter.HandleViewDidLoadCalled  
0xB in Cirrious.CrossCore.Core.MvxDelegateExtensionMethods.Raise    
0xD in Cirrious.CrossCore.Touch.Views.MvxEventSourceViewController.ViewDidLoad  
  在p中的Demo.iOS.FirstView.ViewDidLoad中的

0x2:[path] \ View \ FirstView.cs:34,-1
      UIKit.UIApplication.UIApplicationMain中的0xA6       位于/Developer/MonoTouch/Source/monotouch/src/UIKit/UIApplication.cs:62,4的UIKit.UIApplication.Main中的0xB       UIKit.UIApplication.Main中的0x3B位于/Developer/MonoTouch/Source/monotouch/src/UIKit/UIApplication.cs:46,5
      Demo.iOS.Application.Main中的0x8位于c:[path] \ Main.cs:17,-1

1 个答案:

答案 0 :(得分:1)

Mvx Touch应用程序中的默认容器使用以下代码创建视图:

            CurrentRequest = request;
            var viewType = GetViewType(request.ViewModelType);
            if (viewType == null)
                throw new MvxException("View Type not found for " + request.ViewModelType);

            var view = CreateViewOfType(viewType, request);
            view.Request = request;
            return view;

来自https://github.com/MvvmCross/MvvmCross/blob/1eeea41e110934e52bf7e6682d8751b885206844/Cirrious/Cirrious.MvvmCross.Touch/Views/MvxTouchViewsContainer.cs#L31

每个View然后使用隐藏在ViewModel中的说明加载/找到自己的Request

如果Request为空,则Mvx默认使用某些启发式方法,根据使用View类名的约定创建类型的默认ViewModel。


在您的情况下,我认为最好的解决方案是在ViewController上设置Request属性 - 例如

                case SingletonViewModelLocator.SecondViewValue:
                    viewController = new SecondView() { Request = request };
                    MasterNavigationController.PushViewController(viewController, true);
                    return;

但是,您也可以通过在SecondView中提供有关预期的ViewModel类型的提示来执行此操作...您可以通过使用类型覆盖ViewModel属性来执行此操作,方法是继承来自MvxViewController<T>,为视图模型类型(MvxViewFor)提供属性提示,或者在Setup期间添加一些特殊查找

注意 - 你的问题也告诉我你在ViewModel查询方面做了一些单身魔术,所以你可能需要调整这个答案来匹配任何东西......