在Windows Phone 8.1上使用Caliburn.Micro的多视图模型使用单一视图

本文关键字:视图 Windows 模型 单一 Micro Caliburn Phone | 更新日期: 2023-09-27 18:24:57

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

我发现ViewLocator.LocateTypeForModelType是一个用于将ViewModels映射到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,那么我的方法会返回正确的View。

应用程序导航到正确的视图,但从未创建ViewModel。有点像Caliburn。Micro忘记了ViewModel,或者正在寻找一个使用不同约定的。

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

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

关于如何处理这个问题,有什么想法吗?

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

在Windows Phone 8.1上使用Caliburn.Micro的多视图模型使用单一视图

除了顶级导航之外,这种解决方案在其他任何地方都适用。原因是有一种"双重调度:当你导航时会发生。

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

  1. 您的代码告诉导航服务导航到ProductViewModel
  2. 它使用ViewLocator(您已在其中注入代码)来定位ProductView,并告诉Frame导航到该位置
  3. 导航服务然后对ProductView的导航事件作出响应,并使用ViewModelLocator定位正确的视图模型
  4. 然后它实例化并绑定这个视图模型

导航服务中的这种视图模型到视图模型的步骤会导致代码出现问题。

您应该能够创建伪视图,只需继承基本视图而不添加任何内容。因此,如果您有MySharedView.xaml,那么声明下面的内容就足够了。

public class SecondView : MySharedView { }

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

相关文章: