c# - 从 DLL 动态加载 WPF View 和 View 模型

标签 c# .net wpf user-controls .net-assembly

我在 WPF 中创建了一个向导,其中包含作为 UserControl 对象的页面。我要做的是从包含以下内容的 .DLL 文件加载插件:

  • 插件逻辑的代码文件。
  • 一个 XAML 用户控件,它将显示插件的配置选项,显示在主向导中。
  • 用户控件的 View 模型。

我已经能够成功加载并实例化 UserControl 对象以及 View 模型,而且我已经达到了控件按预期出现在它自己的向导页面中的阶段。 (这可能是正确实例化的 View 模型,因为我在 View 模型中设置了向导页面的标题并且一切正常)

我遇到的问题是我从 DLL 加载的 UserControl 没有正确显示。它不显示 UserControl 内容,它只显示 x:Class="MyDLL.MyCustomUserControl" 行中的明文 MyDLL.MyCustomUserControl,其中实际的用户控件应该是。

我从 DLL 加载的用户控件的内容是:

<UserControl x:Class="MyDLL.MyCustomUserControl"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         mc:Ignorable="d" 
         d:DesignHeight="300" d:DesignWidth="300">
<StackPanel>
    <Label Content="This is the Plugin Options Page" />
    <TextBox Text="{Binding Path=PluginStringText}" />
</StackPanel>
</UserControl>

用户控件的 View 模型中存在属性PluginStringText

我有一种感觉,在从 DLL 加载 View 模型后,我需要以某种方式将 View 模型分配或绑定(bind)到用户控件。 作为向导的一部分,有一个部分用于定义数据模板(这是另一个包含向导页面的 UserControl),但我不知道如何在运行时实际添加额外的模板。我感觉这是导致问题的原因。

搜索许多主题表明我可能可以通过 View 的代码隐藏文件来完成此操作,但是我无法首先获得对 View 代码隐藏的引用以调用方法。有没有办法从 View 的 View Model 类中添加新的 DataTemplate 条目?

<UserControl.Resources>

    <DataTemplate DataType="{x:Type viewModel:ExistingPage1ViewModel}">
        <view:ExistingPage1View />
    </DataTemplate>

    <DataTemplate DataType="{x:Type viewModel:ExistingPage2ViewModel}">
        <view:ExistingPage2View />
    </DataTemplate>
<...>

如果有人能指出正确的方向,请提前致谢

最佳答案

我找到了解决这个问题的方法。 问题如我所料,ViewModel 数据类型与用于呈现 ViewModel 的 View 之间没有映射。

我在这里发现了一个有用的指南 http://www.ikriv.com/dev/wpf/DataTemplateCreation/其中解释了如何在代码中创建新的数据模板,这与您在 XAML 中对模板进行硬编码非常相似。

一切都很好,但我仍然必须找到一种方法来调用创建数据模板的方法。

好吧 - 事实证明我根本不需要在后面的代码中调用该方法!我只是将创建数据模板的方法直接放在负责填充向导页面的 View 模型中。

这还有一个额外的好处,就是我不必在 xaml 中对现有页面数据模板进行硬编码。


我将添加在 http://www.ikriv.com/dev/wpf/DataTemplateCreation/ 引用的代码供将来引用:

创建DataTemplate对象的方法:

DataTemplate CreateTemplate(Type viewModelType, Type viewType)
{
    const string xamlTemplate = "<DataTemplate DataType=\"{{x:Type vm:{0}}}\"><v:{1} /></DataTemplate>";
    var xaml = String.Format(xamlTemplate, viewModelType.Name, viewType.Name, viewModelType.Namespace, viewType.Namespace);

    var context = new ParserContext();

    context.XamlTypeMapper = new XamlTypeMapper(new string[0]);
    context.XamlTypeMapper.AddMappingProcessingInstruction("vm", viewModelType.Namespace, viewModelType.Assembly.FullName);
    context.XamlTypeMapper.AddMappingProcessingInstruction("v", viewType.Namespace, viewType.Assembly.FullName);

    context.XmlnsDictionary.Add("", "http://schemas.microsoft.com/winfx/2006/xaml/presentation");
    context.XmlnsDictionary.Add("x", "http://schemas.microsoft.com/winfx/2006/xaml");
    context.XmlnsDictionary.Add("vm", "vm");
    context.XmlnsDictionary.Add("v", "v");

    var template = (DataTemplate)XamlReader.Parse(xaml, context);
    return template;
}

然后需要将此 DataTemplate 注册为应用程序资源:

注册数据模板:

Application.Current.Resources.Add(template.DataTemplateKey;, template);

再次感谢 Ivan Krivyakov 在 http://www.ikriv.com/dev/wpf/DataTemplateCreation/ 提供的代码

关于c# - 从 DLL 动态加载 WPF View 和 View 模型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20930227/

相关文章:

c# - 刷新 DB First EDMX 时如何保留 StoreGeneratedPattern 设置?

c# - 有谁知道一种更快的方法来执行 String.Split()?

c# - 字典中的链接项

c# - Gridview RowDataBound 显示每一行的隐藏列

c# - 在 WPF ListView 中如何防止自动滚动?

c# - 遍历事件日志条目集合,IndexOutOfBoundsException

c# - 无法解码 .NET SslStream 握手中的完整密码列表

c# - 更改按钮模板内的图像源

WPF:在两个显示器上开发,单独的设计编辑器和 xaml 代码

c# - 打印多个 datagridview 页面