简体   繁体   English

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

[英]Using single View for multiple ViewModels with Caliburn.Micro on Windows Phone 8.1

I have a Windows Phone 8.1 app using Caliburn.Micro. 我有一个使用Caliburn.Micro的Windows Phone 8.1应用程序。 In the app I have a few ViewModels that fetch data in different way and with different logic but show them in the same way. 在应用程序中,我有一些ViewModel以不同的方式和不同的逻辑获取数据,但以相同的方式显示它们。 So I want to make all those ViewModel use the same one View. 所以我想让所有那些ViewModel使用相同的View。

I found out that ViewLocator.LocateTypeForModelType is a method that gets executed for mapping ViewModels to Views. 我发现ViewLocator.LocateTypeForModelType是一个为将ViewModels映射到Views而执行的方法。 So I override it to use my custom attribute when present: 所以我重写它以在使用时使用我的自定义属性:

        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);
        };

Stepping through the it seems to work fine. 单步执行它似乎工作正常。 If I navigate to a ViewModel and that ViewModel has a UseView, my method returs the correct View. 如果我导航到ViewModel并且ViewModel有一个UseView,我的方法会返回正确的View。

The app navigates to the correct View but the ViewModel is never created. 该应用程序导航到正确的视图,但从未创建ViewModel。 Kind of like Caliburn.Micro forgot about the ViewModel, or was looking for one using a different convention, or something. 有点像Caliburn.Micro忘了ViewModel,或者正在寻找一个使用不同的约定或其他东西。

I found out that ViewModelLocator.LocateTypeForViewType is called after navigation to a View to resolve the ViewModel. 我发现ViewModelLocator.LocateTypeForViewType是导航后调用视图来解决视图模型。 The ViewModel type from the previous step seems to be forgotten completely. 上一步中的ViewModel类型似乎完全被遗忘了。

In ViewModelLocator.LocateTypeForViewType I only have access to the View type and I do not know, how to make it resolve the correct ViewModel from the previous step. ViewModelLocator.LocateTypeForViewType我只能访问View类型,我不知道如何使其解析上一步中正确的ViewModel。 I could scan all the ViewModel and find the ones with the correct attribute, but I would not know which one to choose. 我可以扫描所有ViewModel并找到具有正确属性的ViewModel,但我不知道选择哪一个。

Any ideas on how to approach this? 关于如何处理这个的任何想法?

Here is a minimal project showing my setup: https://dl.dropboxusercontent.com/u/73642/CMVMTest.zip 这是一个显示我的设置的最小项目: https//dl.dropboxusercontent.com/u/73642/CMVMTest.zip

This sort of solution would work everywhere else except for the top level navigation. 除了顶级导航之外,这种解决方案可以在其他任何地方使用。 The reason for this is there is sort of a "double dispatch: going on when you navigate. 这样做的原因是有一种“双重调度:当你导航时继续进行。

As you know the Frame or PhoneNavigationFrame control (depending on WinRT or Silverlight) is view based in it's navigation. 如您所知, FramePhoneNavigationFrame控件(取决于WinRT或Silverlight)是基于其导航的视图。 So the steps look a little like this. 所以步骤看起来有点像这样。

  1. Your code tells the navigation servie=ce to navigate to ProductViewModel . 您的代码告诉导航servie = ce导航到ProductViewModel
  2. It uses ViewLocator (where you've injected your code) to locate ProductView and tells the Frame to navigate to that. 它使用ViewLocator (您已注入代码的位置)来定位ProductView并告诉Frame导航到那个。
  3. The navigation service then responds to the navigating event to ProductView and locates the correct view model using ViewModelLocator . 然后导航服务响应导航事件到ProductView并使用ViewModelLocator定位正确的视图模型。
  4. It then instantiates and binds this view model. 然后它实例化并绑定此视图模型。

This sort of view model to view to view model step in navigation service causes the hiccup in your code. 这种用于查看导航服务中的模型步骤的视图模型会导致代码中的打嗝。

You should be able to create dummy views that simply inherit the base view and add nothing. 您应该能够创建简单地继承基本视图并且不添加任何内容的虚拟视图。 So if you have MySharedView.xaml then declaring what's below should be enough. 因此,如果你有MySharedView.xaml那么声明下面的内容就足够了。

public class SecondView : MySharedView { }

It's not ideal I know, but does get you the reuse you're after. 我知道它并不理想,但确实可以让你重复使用。 Having the navigation service remember the view model between the navigating and navigated events becomes complicated with all the external factors that can cause navigation as well. 让导航服务记住导航事件和导航事件之间的视图模型变得复杂,所有外部因素也会导致导航。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM