Caliburn micro in no Application object mode, like in AutoCAD dll plugin

痞子三分冷 提交于 2019-12-05 22:53:47
Jatin

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.

Edit: 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!

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

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

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

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).

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

regards, Nirvan

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!