在Windows Phone 8.1上使用单个View查看多个ViewModel和Caliburn.Micro

时间:2015-11-27 14:26:49

标签: c# xaml mvvm windows-phone-8.1 caliburn.micro

我有一个使用Caliburn.Micro的Windows Phone 8.1应用程序。在应用程序中,我有一些ViewModel以不同的方式和不同的逻辑获取数据,但以相同的方式显示它们。所以我想让所有ViewModel使用相同的View。

我发现ViewLocator.LocateTypeForModelType是一个将ViewModel映射到Views的执行方法。所以我重写它以使用我的自定义属性:

        var original = ViewLocator.LocateTypeForModelType;

        ViewLocator.LocateTypeForModelType = (modelType, displayLocation, context) =>
        {
            var useViewAttributes = modelType.GetTypeInfo().GetCustomAttributes<UseViewAttribute>(true);

            if (useViewAttributes.Count() == 1)
            {
                var viewTypeName = string.Concat(modelType.Namespace.Replace("Model", string.Empty), ".", useViewAttributes.First().ViewName);
                var type = AssemblySource.FindTypeByNames(new List<string>() { viewTypeName });
                return type;
            }

            return original(modelType, displayLocation, context);
        };

单步执行它似乎工作正常。如果我导航到ViewModel并且ViewModel有一个UseView,我的方法会返回正确的视图。

该应用导航到正确的视图,但从未创建ViewModel。有点像Caliburn.Micro忘记了ViewModel,或正在寻找使用不同约定的东西。

我发现在导航到View以解析ViewModel后会调用ViewModelLocator.LocateTypeForViewType。上一步中的ViewModel类型似乎完全被遗忘了。

ViewModelLocator.LocateTypeForViewType我只能访问View类型,我不知道,如何让它解决上一步中正确的ViewModel。我可以扫描所有ViewModel并找到具有正确属性的ViewModel,但我不知道选择哪一个。

有关如何处理此事的任何想法?

这是一个显示我的设置的最小项目:https://dl.dropboxusercontent.com/u/73642/CMVMTest.zip

1 个答案:

答案 0 :(得分:0)

除了顶级导航之外,这种解决方案可以在其他任何地方使用。这样做的原因是有一种“双重调度:当你导航时继续。

如您所知,FramePhoneNavigationFrame控件(取决于WinRT或Silverlight)是基于其导航的视图。所以步骤看起来有点像这样。

  1. 您的代码告诉导航服务= ce导航到ProductViewModel
  2. 使用ViewLocator(您已注入代码的位置)找到ProductView并告诉Frame导航到该代码。
  3. 然后,导航服务会将导航事件响应到ProductView,并使用ViewModelLocator找到正确的视图模型。
  4. 然后实例化并绑定此视图模型。
  5. 这种用于查看导航服务中的模型步骤的视图模型会导致代码中的打嗝。

    您应该能够创建简单地继承基本视图并且不添加任何内容的虚拟视图。因此,如果您有MySharedView.xaml,那么声明下面的内容就足够了。

    public class SecondView : MySharedView { }

    我知道这并不理想,但确实可以让你重复使用。让导航服务记住导航和导航事件之间的视图模型变得复杂,所有外部因素也会导致导航。