从插件程序集将WPF UI加载到MVVM应用程序中 [英] Load WPF UI into MVVM application from plug-in assembly

查看:120
本文介绍了从插件程序集将WPF UI加载到MVVM应用程序中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一个使用插件体系结构来扩展其功能的应用程序.从插件加载WPF UI的最佳方法是什么?

I am working on an application that uses a plug-in architecture to expand it's functionality. What is the best way to load WPF UIs from a plug-in?

我将有一个列表框,列出所有可用的插件.选择插件时,应在ContentControl中显示该插件中定义的WPF UI.我想到的选项包括:

I will have a listbox listing all of the available plug-ins. When a plug-in is selected, a WPF UI defined in the plug-in should be displayed in a ContentControl. The options I have thought of include:

  • 要求创建一个实现特定接口的UserControl.我认为这将使插件创建变得容易.实施一个接口,您就很好了.使用此方法的问题是如何将UserControl动态加载到ContentControl中.另外,由于我使用的是MVVM设计模式,因此似乎DataTemplateUserControl更为可取.
  • 允许从插件中加载DataTemplate.我相信这将要求该插件包含以某种方式命名的XAML文件.我的应用程序会将DataTemplate读入我的资源字典中,例如在此问题中.我已经看到了很多与此类似的问题,除了它们通常只需要加载一个附加的预定义程序集即可从中获取DataTemplates.此问题将需要搜索DataTemplates的任意数量的未知程序集.
  • Require a UserControl to be created that implements a specific interface. I am thinking this would make it easy for plug-in creation. Implement an interface and you are good to go. My question with this method is how to dynamically load the UserControl into a ContentControl. Also, since I am using the MVVM design pattern it seems that a DataTemplate would be preferred over a UserControl.
  • Allow a DataTemplate to be loaded from the plug-in. I believe this would require the plug-in to contain a XAML file named a certain way. My application would read the DataTemplate into my resource dictionary like shown in this question. I have seen quite a few questions similar to this, except they usually only need to load one additional, predefined assembly to get DataTemplates from. This problem would require any number of unknown assemblies to be searched for DataTemplates.

如果我选择第二个选项,我想可以选择DataTemplate,类似于此答案所描述的方式.

If I choose the second option, I think I could select the DataTemplate similarly to how this answer describes.

您认为哪种方法更好?还是您有更好的方法来做到这一点?

Which method do you think is better? Or do you have a better way to accomplish this?

推荐答案

我做了与DataTemplates相似的事情.我使用 MEF 加载插件,然后加载了Dictionary并引用了ViewModelView在启动时.该插件使用3个主要组件构建.

I did something similar like mentioned with DataTemplates. I used MEF to load plugins and then loaded a Dictionary with a reference to the ViewModel and View at startup. The plugin isbuilt using 3 main components.

IBasePlugin.cs

这个简单的界面允许我们为插件创建框架.这将仅包含非常基本的内容,因为这是我们将使用MEFImport插件插入到主应用程序中的方式.

This simple interface allows us to create a skeleton for the plugin. This will only contains the very basics, as this is what we will use to Import plugins to our main application using MEF.

public interface IBasePlugin
{
    WorkspaceViewModel ViewModel { get; }
    ResourceDictionary View{ get; }
}

Plugin.cs

下一部分是Plugin.cs文件.它包含了我们插件的所有属性,以及所有必要的参考.例如我们的View& ViewModel.

The next part is the Plugin.cs file. It contains all the properties of our plugin, as well as all the necessary references; such as to our View & ViewModel.

[Export(typeof(IBasePlugin))]
public class Plugin : IBasePlugin
{
    [Import]
    private MyPluginViewModel _viewModel { get; set; }
    private ResourceDictionary _viewDictionary = new ResourceDictionary();

    [ImportingConstructor]
    public Plugin()
    {
        // First we need to set up the View components.
        _viewDictionary.Source =
            new Uri("/Extension.MyPlugin;component/View.xaml",
            UriKind.RelativeOrAbsolute);
    }

    ....Properties...

}

View.xaml

这是一个DataTemplate,其中包含对插件ViewViewModel的引用.这就是我们将Plugin.cs加载到主应用程序中所使用的,以便该应用程序和WPF将知道如何将所有内容绑定在一起.

This is a DataTemplate containing a Reference to the plugin View and ViewModel. This is what we will use for Plugin.cs to load into the main application, so that the application and WPF will know how to bind everything together.

<DataTemplate DataType="{x:Type vm:MyPluginViewModel}">
    <vw:MyPluginView/>

然后,我们使用 MEF 加载所有插件,并将其提供给我们负责的工作区ViewModel处理插件,并将其存储在ObservableCollection中,该ObservableCollection将用于显示所有可用的插件.

We then use MEF to load all the plugins, feed them to our Workspace ViewModel responsible of handling the Plugins, and store them in an ObservableCollection that will be used to display all the available plugins.

我们用于加载插件的代码如下所示.

The code we use to load plugins can look something like this.

var plugins = Plugins.OrderBy(p => p.Value.ViewModel.HeaderText);
foreach (var app in plugins)
{
    // Take the View from the Plugin and Merge it with,
    // our Applications Resource Dictionary.
    Application.Current.Resources.MergedDictionaries.Add(app.Value.View)

    // THen add the ViewModel of our plugin to our collection of ViewModels.
    var vm = app.Value.ViewModel;
    Workspaces.Add(vm);
}

一旦DictinoaryViewModel都已从我们的插件加载到我们的应用程序中,我们就可以使用例如TabControl来显示集合.

Once both the Dictinoary and ViewModel has been loaded from our Plugin into our application we can display the collection using for example a TabControl.

<TabControl ItemsSource="{Binding Workspaces}"/>

我也给出了类似的答案

I also gave a similar answer here as well with some additional details that you might find interesting.

这篇关于从插件程序集将WPF UI加载到MVVM应用程序中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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