从插件程序集将WPF UI加载到MVVM应用程序中 [英] Load WPF UI into MVVM application from plug-in assembly
问题描述
我正在开发一个使用插件体系结构来扩展其功能的应用程序.从插件加载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设计模式,因此似乎DataTemplate
比UserControl
更为可取. - 允许从插件中加载
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 theUserControl
into aContentControl
. Also, since I am using the MVVM design pattern it seems that aDataTemplate
would be preferred over aUserControl
. - 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 theDataTemplate
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 getDataTemplates
from. This problem would require any number of unknown assemblies to be searched forDataTemplates
.
如果我选择第二个选项,我想可以选择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
并引用了ViewModel
和View
在启动时.该插件使用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
这个简单的界面允许我们为插件创建框架.这将仅包含非常基本的内容,因为这是我们将使用MEF
将Import
插件插入到主应用程序中的方式.
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
,其中包含对插件View
和ViewModel
的引用.这就是我们将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);
}
一旦Dictinoary
和ViewModel
都已从我们的插件加载到我们的应用程序中,我们就可以使用例如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屋!