3

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

由于 AutoCAD 插件类型(dll),插件没有应用程序对象,因此必须为此自定义引导程序。根据此处的 Caliburn Micro 文档(向下滚动到“在 Office 和 WinForms 应用程序中使用 Caliburn.Micro”),我们可以继承非通用引导程序并将“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 窗体。在 Windows 窗体的加载事件中,我创建了一个实例定制的 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 永远不会加载。

4

1 回答 1

4

此问题已得到解决。问题是在 AutoCAD 本身中加载支持程序集(dll)会出错。请参阅线程。正确加载程序集后,我可以使用 Caliburn Micro,它也可以在非 WPF 环境中工作。

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

我的插件.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();
    }

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

Bootstrapper 没有太大区别,只是我们将 false 传递给文档中提到的基本构造函数。这是引导程序的样子

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

自定义窗口管理器.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)。

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

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

问候, 尼尔文

于 2012-12-03T12:31:50.003 回答