Caliburn micro 在无应用程序对象模式下,就像在 AutoCAD dll 插件中一样 [英] Caliburn micro in no Application object mode, like in AutoCAD dll plugin

查看:21
本文介绍了Caliburn micro 在无应用程序对象模式下,就像在 AutoCAD dll 插件中一样的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am using Caliburn Micro to develop WPF application. A few of views of this application needs to be loaded in an AutoCAD environment. The AutoCAD programming environment allows developement of AutoCAD plugins (of type dll) and load them into the AutoCAD environment.

由于 AutoCAD 插件类型 (dll),插件没有应用程序对象,因此必须为此自定义引导程序.根据 Caliburn Micro 文档 此处(向下滚动到使用 Caliburn.Micro in Office and WinForms Applications")我们可以继承非通用引导程序并将false"传递给基本构造函数的useApplication"参数.所以,我继续创建了定制的引导程序.

Because of AutoCAD plugin type(dll), the plugin does not have an Application Object, so the bootstrapper has to be customized for that. According to the Caliburn Micro documentation here (Scroll down to "Using Caliburn.Micro in Office and WinForms Applications") we can inherit the non-generic bootstrapper and pass "false" to the base constructor's "useApplication" parameter. So, I went ahead and created the customized bootstrapper.

问题是 ConfigureContainer() 覆盖永远不会被调用并且没有任何东西被初始化.另外,我不确定如何使用 ViewModel 第一个概念加载 ShellView.这是我到现在为止想出来的一些代码.

The issue is that the ConfigureContainer() override never gets called and nothing gets initialized. Also, I am not sure how to load the ShellView using ViewModel first concept. Here is some code that I have come up till now.

引导程序

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

我有一个 Windows 窗体,AutoCAD 在请求时加载它.在 Windows 窗体的加载事件中,我创建了一个实例定制的 caliburn 微型引导程序,并期望引导程序执行所有魔术并加载 Shell.但是外壳不加载.我在 AutoCAD 中显示空白窗口.这是 Windows 窗体的编码方式.

I have a windows form which the AutoCAD loads when requested. In the Windows Form's loaded event, I create an instance cuztomized caliburn micro bootstrapper and expect the boot strapper to do all the magic and load the Shell. But the Shell does not load. I get the blank window displayed in the AutoCAD. Here is how the Windows Form is coded.

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 永远不会加载.

So in summary, I am trying use Caliburn Micro in an hosted environment which is not loaded using the Application object. I am unable to configure Caliburn Micro, as the ShellView never loads.

推荐答案

此问题已解决.问题是在 AutoCAD 本身中加载支持程序集 (dll) 时出错.请参阅这个 线程.一旦正确加载了程序集,我就可以使用 Caliburn Micro,它也可以在非 WPF 环境中使用.

This issue has been resolved. The problem was that loading of supporting assemblies (dll's) in AutoCAD itself was giving error. Please See this thread. Once the assemblies were loaded correctly, I could use the Caliburn Micro and it works in non-WPF environment too.

我会合乎逻辑地展示这个过程.我在纯 wpf 应用程序中开发的 wpf 屏幕将在 AutoCAD 插件中重新使用,但由于 autocad 插件是类库(dll),因此没有可用的 Application 对象.当 AutoCAD 启动时,插件代码会在我可以初始化 caliburn 微引导程序的地方执行.这是相关的插件代码.

I will logically show the process. The wpf screen that I had developed in a pure wpf application was to be re-used in AutoCAD plugin, but since autocad plugin's are class library(dll), there is no Application object available. When AutoCAD is launched, the plugin code executes where I could initialize the caliburn micro bootstrapper. Here is the relevant plugin code.

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

请注意,该应用程序具有显式关闭模式.这是必需的,虽然我不记得为什么!

Note that the Application has a shutdown mode of Explicit. This is required, although I don't remember why!

Bootstrapper 没有太大区别,除了我们将 false 传递给文档中提到的基本构造函数.这是 Bootstrapper 的样子

There is not much difference in the Bootstrapper, except that we pass false to the base constructor as mentioned in documentation. Here is what the Bootstrapper looks like

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有点相关,但为了完整起见,我将分享.

This is the configuration part which happens only once when the plugin is loaded the calibur micro is configured. After this the code is a bit related to AutoCAD but for the sake of completeness, I will share.

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

QueryRelay.cs This class accepts command input from AutoCAD user and then displays the requested View

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 的代码

Since the windows in AutoCAD are shown using the AutoCAD's API, I had to customize the Caliburn Micro WindowManager slightly. Here is the code for the 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(上面代码中的 rootModel)创建视图,然后使用 AutoCAD API 将其加载到 AutoCAD 中.视图的显示方式取决于托管应用程序(在我的情况下为 AutoCAD).

I ask the CaliburnMicro to create View from ViewModel(rootModel in above code), which then is loaded in AutoCAD using the AutoCAD API. How the View is shown will depend on the hosting application (AutoCAD in my case).

最后必须在 BootStrapper 配置中注册 CustomWindowManager

Finally the CustomWindowManager has to be registered in the BootStrapper Configure

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

问候,涅盘

这篇关于Caliburn micro 在无应用程序对象模式下,就像在 AutoCAD dll 插件中一样的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆