从WinForms托管的WPF控件加载/使用资源字典

时间:2009-02-23 21:33:53

标签: wpf winforms interop resources elementhost

我有一个Windows窗体应用程序需要在运行时托管WPF控件。我有基本的托管和交互完成(使用ElementHost控件),一切正常,直到我尝试做一些需要WPF控件来使用定义的一些自定义资源字典。 (WPF控件及其所有资源字典都在同一个WPF控件库DLL中定义。)

一旦发生这种情况,我就会收到一堆看起来像这样的错误:

System.Windows.ResourceDictionary Warning: 9 : Resource not found; ResourceKey='DocumentHeaderInterestStyle'

我找到一个reference链接因归档而显示为this 可能与最初引用的文章相同)。谈到这一点,但似乎这篇文章正在接近WPF方面的内容,但我真的不想对WPF控件进行更改,因为一切都在独立的WPF应用程序中运行。

如果实现这一目标的唯一方法是在WPF端进行更改,我可以进行这些更改(我不负责WPF控件库,但是那个也适用于同一家公司的人,所以它不是除了花时间进行更改之外的其他问题。)但我希望能在WinForms方面做些什么来实现这一点。

WPF控件库在项目中定义了一个名为“Default.xaml”的资源字典文件,其中包含以下属性:

构建行动:页面 复制到输出目录:不要复制 自定义工具:MSBuild:编译

独立的WPF应用程序在其App.xaml文件中包含以下条目:

    <ResourceDictionary x:Uid="ResourceDictionary_1">
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary x:Uid="ResourceDictionary_2" Source="/SmartClient.Infrastructure;component/Themes\Default.xaml"/>
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>

似乎控制库应该已经知道如何获取其资源。使用Resources.MergedDictionaries.Add()似乎应该可以工作,但是我从哪里获得现有字典的实例?

3 个答案:

答案 0 :(得分:4)

假设你知道你需要什么资源(听起来像你这样做),你应该能够自己“注入”它们。类似的东西:

var wpfControl = new ...;
wpfControl.Resources.Add(...);
elementHost.Child = wpfControl;

在您的问题中,您提到控件库中存在现有的资源字典。如果是这样,你可以这样做:

var wpfControl = new ...;
wpfControl.Resources.MergedDictionaries.Add(/* instance of existing dictionary */);
elementHost.Child = wpfControl;

答案 1 :(得分:2)

为了加载嵌入到程序集中的资源字典,我在运行时使用了以下代码片段来加载它们:

//using System.Windows
ResourceDictionary dict = new ResourceDictionary();
dict.Source = new Uri("MyResourceDictionary.xaml", UriKind.Relative);

Application.Current.Resources.MergedDictionaries.Add(dict);

这也适用于在可执行文件目录中加载字典。

答案 2 :(得分:0)

假设您将样式/模板/资源分为多个文件Resources1.xamlResources2.xaml,您可以将它们聚合到一个资源字典(AllResources.xaml)中。资源字典可以轻松添加到控件的xaml文件中的控件中。请参阅下面的示例。

(!)Resources1.xamlResources2.xamlAllResources.xaml制作行动设为 Page

Resources1.xaml

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

    <ControlTemplate x:Key="ScrollViewerControlTemplate" TargetType="{x:Type ScrollViewer}">
        ...
    </ControlTemplate>

    <LinearGradientBrush x:Key="VerticalScrollBarBackground" EndPoint="1,0" StartPoint="0,0">
        ...
    </LinearGradientBrush>

    <Style x:Key="StyleA" TargetType="{x:Type ScrollBar}">
        ...
    </Style>

</ResourceDictionary>

Resources2.xaml

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">


    <Style x:Key="StyleB" TargetType="{x:Type ScrollBar}">
        ...
    </Style> 

    <Style x:Key="StyleC" TargetType="{x:Type TextBlock}">
        ...
    </Style>

</ResourceDictionary>

AllResources.xaml

将资源词典来源添加为相对路径到AllResources.xaml

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
    <ResourceDictionary.MergedDictionaries>
        <ResourceDictionary Source="Resources1.xaml" />
        <ResourceDictionary Source="Resources2.xaml" />
    </ResourceDictionary.MergedDictionaries>
</ResourceDictionary>

最后在你的UserControl中

<UserControl.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="pack://application:,,,/projectName;component/PathToTheFileRelativeToProjectRootDirectory/AllResources.xaml
        <converters:StringToUpperCaseConverter x:Key="StringToUpperCaseConverter" />
        <converters:LocalizationEntryToStringCaseConverter x:Key="LocalizationEntryToStringCaseConverter" />
    </ResourceDictionary>
</UserControl.Resources>