我做了类似DataTemplates 提到的事情。我使用MEF 加载插件,然后在启动时加载Dictionary 并引用ViewModel 和View。该插件使用 3 个主要组件构建。
IBasePlugin.cs
这个简单的界面允许我们为插件创建一个骨架。这将只包含非常基础的内容,因为这是我们将使用Import 插件到我们的主应用程序使用MEF。
public interface IBasePlugin
{
WorkspaceViewModel ViewModel { get; }
ResourceDictionary View{ get; }
}
Plugin.cs
下一部分是Plugin.cs 文件。它包含我们插件的所有属性,以及所有必要的参考;比如我们的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 知道如何将所有内容绑定在一起。
<DataTemplate DataType="{x:Type vm:MyPluginViewModel}">
<vw:MyPluginView/>
然后我们使用MEF 加载所有插件,将它们提供给我们负责处理插件的工作区ViewModel,并将它们存储在一个ObservableCollection 中,用于显示所有可用的插件。
我们用来加载插件的代码可能看起来像这样。
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 来显示集合。
<TabControl ItemsSource="{Binding Workspaces}"/>
我也给出了类似的答案here 以及一些您可能会感兴趣的其他细节。