从插件程序集中将WPF UI加载到MVVM应用程序中

bur*_*t11 11 c# wpf mvvm

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

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

  • 需要UserControl创建实现特定接口的a.我认为这将使插件创建变得容易.实现一个界面,你很高兴.我对这个方法的问题是如何动态加载UserControl到a ContentControl.此外,由于我使用的是MVVM设计模式,因此似乎DataTemplate优于a UserControl.
  • 允许DataTemplate从插件加载.我相信这需要插件包含一个名为某种方式的XAML文件.我的应用程序将读DataTemplate入我的资源字典,如此问题中所示. 我已经看到了很多类似的问题,除了它们通常只需要加载一个额外的预定义程序集来获取DataTemplates.此问题需要搜索任意数量的未知程序集DataTemplates.

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

您认为哪种方法更好?或者你有更好的方法来实现这一目标吗?

ean*_*son 12

我做了类似的事情DataTemplates.我用MEF加载插件,然后装载一个Dictionary与所述的基准ViewModelView在启动时.该插件使用3个主要组件构建.

IBasePlugin.cs

这个简单的界面允许我们为插件创建一个骨架.这将只包含非常基础,因为这是我们将使用Import插件到我们的主应用程序MEF.

public interface IBasePlugin
{
    WorkspaceViewModel ViewModel { get; }
    ResourceDictionary View{ get; }
}
Run Code Online (Sandbox Code Playgroud)

Plugin.cs

下一部分是Plugin.cs文件.它包含我们插件的所有属性,以及所有必要的参考; 比如我们ViewViewModel.

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

}
Run Code Online (Sandbox Code Playgroud)

View.xaml

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

<DataTemplate DataType="{x:Type vm:MyPluginViewModel}">
    <vw:MyPluginView/>
Run Code Online (Sandbox Code Playgroud)

然后我们使用MEF加载所有插件,将它们提供给ViewModel负责处理插件的Workspace ,并将它们存储在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);
}
Run Code Online (Sandbox Code Playgroud)

一旦双方DictinoaryViewModel从我们的插件安装到我们的应用程序已经被加载,我们可以通过显示例如集合TabControl.

<TabControl ItemsSource="{Binding Workspaces}"/>
Run Code Online (Sandbox Code Playgroud)

在这里也给出了类似的答案以及一些您可能感兴趣的其他细节.