在Caliburn.Micro中将派生的ViewModels映射到基类View

本文关键字:映射 ViewModels 基类 View 派生 Caliburn Micro | 更新日期: 2023-09-27 18:12:58

我有一个基本的ViewModel和关联的View。我也有多个派生的ViewModel从基本的ViewModel,但我想使用基本视图显示。

Base ViewModel和View:

  • vm: MyCompany.MyApp.Modules.Wizard.ViewModels.WizardViewModel
  • vw: MyCompany.MyApp.Modules.Wizard.Views.WizardView

源自WizardViewModel:

  • vm: MyCompany.MyApp.Modules.NewSpec.ViewModels.NewSpecViewModel : WizardViewModel
  • vw: (map to MyCompany.MyApp.Modules.Wizard.Views.WizardView)

  • vm: MyCompany.MyApp.Modules.NewSpec.ViewModels.NewMaterialViewModel : WizardViewModel

  • vw: (map to MyCompany.MyApp.Modules.Wizard.Views.WizardView)

我认为这应该可以使用ViewLocator或ViewModelLocator或NameTransformer中的映射,但我还没有弄清楚。

我正在使用双子座框架与Caliburn。Micro v1.5.2(我计划很快升级到v2)。

这是我尝试过的一件事:

public class NewSpecViewModel : WizardViewModel
{
    // ...
    static NewSpecViewModel()
    {
        // Escape the '.' for the regular expression
        string nsSource = typeof(NewSpecViewModel).FullName.Replace(".", @"'.");
        string nsTarget = typeof(WizardViewModel).FullName;
        nsTarget = nsTarget.Replace("WizardViewModel", "Wizard");
        // nsSource = "MyCompany''.MyApp''.Modules''.NewSpec''.ViewModels''.NewSpecViewModel"
        // nsTarget = "MyCompany.MyApp.Modules.Wizard.ViewModels.Wizard"
        ViewLocator.AddTypeMapping(nsSource, null, nsTarget);
    }
    // ...
}

注:我知道有现有的向导框架(扩展WPF工具包,Avalon向导等),但我不想添加另一个第三方程序集和扩展WPF工具包向导不能正常工作。

P.P.S.我还想在其他地方使用这种样式的基础ViewModel/View映射

在Caliburn.Micro中将派生的ViewModels映射到基类View

这里有[链接](https://caliburnmicro.codeplex.com/discussions/398456)的正确方法。

编辑:由于codeplex正在关闭,下面是讨论中的代码:

var defaultLocator = ViewLocator.LocateTypeForModelType;
ViewLocator.LocateTypeForModelType = (modelType, displayLocation, context) =>
{
    var viewType = defaultLocator(modelType, displayLocation, context);
    while (viewType == null && modelType != typeof(object))
    {
        modelType = modelType.BaseType;
        viewType = defaultLocator(modelType, displayLocation, context);
    }
    return viewType;
};

我知道已经很晚了…但是有一个选项可以将ViewModel直接绑定到视图,也许这对其他人有帮助。

我还会将此绑定附加到基类构造函数。以下内容适合我:

public abstract class WizardViewModel {
    protected WizardViewModel() {
        // this --> points the child class
        ViewModelBinder.Bind(this, new WizardView(), null);
    }
}

这样,每个子类现在都使用WizardView(无需在子类中进行任何额外的编程)。

public class NewSpecViewModel : WizardViewModel {}