Caliburn micro没有应用程序对象模式,就像AutoCAD dll插件一样

时间:2012-12-01 10:55:49

标签: wpf caliburn.micro autocad

我正在使用Caliburn Micro来开发WPF应用程序。需要在AutoCAD环境中加载此应用程序的一些视图。 AutoCAD编程环境允许开发AutoCAD插件(类型为dll)并将其加载到AutoCAD环境中。

由于AutoCAD插件类型(dll),插件没有应用程序对象,因此必须为其自定义引导程序。根据Caliburn Micro文档here (Scroll down to "Using Caliburn.Micro in Office and WinForms Applications"),我们可以继承非通用引导程序并将“false”传递给基础构造函数的“useApplication”参数。所以,我继续创建了自定义引导程序。

问题是,从不调用ConfigureContainer()覆盖,也没有任何内容被初始化。另外,我不确定如何使用ViewModel第一个概念加载ShellView。这是我到现在为止提出的一些代码。

引导程序

public class AutocadMefBootStrapper : Bootstrapper {

    private CompositionContainer container;
    private ElementHost host;

    public AutocadMefBootStrapper(ElementHost host) : base(false) {
        this.host = host;
    }

    protected override void Configure() { //Not getting invoked.
        ...
        var rootViewModel = container.GetExportedValue<IShell>();
        var rootView = ViewLocator.LocateForModel(rootViewModel, null, null);
        host.Child = rootView;
    }
}

我有一个窗口表单,AutoCAD会在请求时加载。在Windows窗体的加载事件中,我创建了一个实例cuztomized caliburn微引导程序,并期望引导过滤器完成所有魔法并加载Shell。但壳牌没有加载。我在AutoCAD中显示了空白窗口。以下是Windows窗体的编码方式。

public partial class WinFormHost : Form {

    private void WinFormHost_Load(object sender, EventArgs e) {
        ElementHost host = new ElementHost();
        host.Dock = DockStyle.Fill;
        Controls.Add(host);
        AutocadMefBootStrapper bootStrapper = new AutocadMefBootStrapper(host);
    }
}

这是我的ShellView

<UserControl x:Class="RelayAnalysis_Autocad.Views.ShellView"
    ...
    <Grid>
        <TextBlock>Hello There</TextBlock>
    </Grid>
</UserControl>

和ShellViewModel

[Export(typeof(IShell))]
public class ShellViewModel : Conductor<object>, IShell {
    protected override void OnActivate() {
        base.OnActivate();
    }
}

总而言之,我正在尝试在未使用Application对象加载的托管环境中使用Caliburn Micro。我无法配置Caliburn Micro,因为ShellView永远不会加载。

1 个答案:

答案 0 :(得分:4)

此问题已得到解决。问题是在AutoCAD中装载支撑组件(dll)本身就给出了错误。请参阅this主题。正确加载程序集后,我可以使用Caliburn Micro,它也适用于非WPF环境。

修改 我将在逻辑上显示该过程。我在纯wpf应用程序中开发的wpf屏幕将在AutoCAD插件中重复使用,但由于autocad插件是类库(dll),因此没有可用的Application对象。启动AutoCAD时,插件代码将执行初始化caliburn微引导程序的位置。这是相关的插件代码。

<强> MyPlugin.cs

public class MyPlugin : IExtensionApplication {

    //Called when plugin is loaded. This is where I load xaml resources, since there is no App.xaml available

    void IExtensionApplication.Initialize() { 
         if (System.Windows.Application.Current == null) {
            new System.Windows.Application { ShutdownMode = ShutdownMode.OnExplicitShutdown }; 
        }
        System.Windows.Application.Current.Resources.MergedDictionaries.Add(System.Windows.Application.LoadComponent(
                new Uri("RelayAnalysis_Autocad;component/Content/Styles/CommonBrushes.xaml", UriKind.Relative)) as ResourceDictionary);
        System.Windows.Application.Current.Resources.MergedDictionaries.Add(System.Windows.Application.LoadComponent(
                new Uri("RelayAnalysis_Autocad;component/Content/Styles/Button.xaml", UriKind.Relative)) as ResourceDictionary);
    ...
        //Load Other xaml resources
    ...
        //Initialize the Bootstrapper
        AutocadMefBootStrapper bootstrapper = new AutocadMefBootStrapper();
    }

    //Called when plugin is unloaded
    void IExtensionApplication.Terminate() {
        // Do plug-in clean up here
        System.Windows.Application.Current.Shutdown();
    }

请注意,Application的关闭模式为Explicit。这是必需的,虽然我不记得为什么!

Bootstrapper没有太大区别,只是我们将false传递给基础构造函数,如文档中所述。以下是Bootstrapper的样子

<强> AutocadMefBootStrapper.cs

public class AutocadMefBootStrapper : Bootstrapper {

    public static CompositionContainer container;

    public AutocadMefBootStrapper()
        : base(false) {
    }

    protected override void Configure() {

        //Create and Add Catalogs.
        AssemblyCatalog currentAssemblyCatalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());

        AssemblyCatalog domainAssemblyCatalog =
            new AssemblyCatalog(Assembly.GetAssembly(typeof(RelayAnalysis_Domain.Entity.Rack)));
    ...
    }

这是配置部件,只有在加载插件时才会发生一次配置的calibur micro。在此之后,代码与AutoCAD有点相关,但为了完整起见,我将分享。

<强> QueryRelay.cs 此类接受来自AutoCAD用户的命令输入,然后显示请求的视图

public class QueryRelay {

    //This command is used to display a particular View. This is entered from AutoCAD Command Window
    public void QueryRelayCommand() {

        //Get the ViewModel for the screen from Container
        AcadRelayListViewModel relayListViewModel = AutocadMefBootStrapper.container.GetExportedValue<AcadRelayListViewModel>();
        IWindowManager windowManager = AutocadMefBootStrapper.container.GetExportedValue<IWindowManager>();
        windowManager.ShowWindow(relayListViewModel);
        ...
    }
}

由于AutoCAD中的窗口是使用AutoCAD的API显示的,因此我必须稍微自定义Caliburn Micro WindowManager。这是CustomWindowManager的代码

<强> CustomWindowManager.cs

public class CustomWindowManager : WindowManager {

    public override void ShowWindow(object rootModel, object context = null, IDictionary<string, object> settings = null) {
        Autodesk.AutoCAD.ApplicationServices.Application.ShowModalWindow(null, CreateWindow(rootModel, false, null, null), false);
    }
}

我要求CaliburnMicro从ViewModel创建View(上面代码中的rootModel),然后使用AutoCAD API将其加载到AutoCAD中。显示视图的方式取决于托管应用程序(在我的情况下为AutoCAD)。

最后,必须在BootStrapper配置

中注册CustomWindowManager
    protected override void Configure() {
        ...
        var batch = new CompositionBatch();
        batch.AddExportedValue<IWindowManager>(new CustomWindowManager());
        container.Compose(batch);
        ...
    }

的问候, NIRVAN