简体   繁体   English

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

[英]Loading/Using Resource Dictionaries from a WinForms hosted WPF control

I have a Windows Forms application that needs to host a WPF control at runtime. 我有一个Windows窗体应用程序需要在运行时托管WPF控件。 I have the basic hosting and interaction complete (using an ElementHost control) and everything works fine until I try to do something that requires the WPF control to make use of some custom resource dictionaries that are defined. 我有基本的托管和交互完成(使用ElementHost控件),一切正常,直到我尝试做一些需要WPF控件来使用定义的一些自定义资源字典。 (The WPF control and all of it's resource dictionaries are all defined in the same WPF Control Library DLL.) (WPF控件及其所有资源字典都在同一个WPF控件库DLL中定义。)

As soon as that happens, I get a bunch of errors that look like this: 一旦发生这种情况,我就会收到一堆看起来像这样的错误:

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

I have found one reference ( link appears dead due to archiving , this might be the same article that was originally referenced). 我找到了一个引用链接因归档而显示为死 可能与最初引用的文章相同)。 that talks about this, but it seems like the article is approaching things more from the WPF side, but I don't really want to have to make changes to the WPF control as everything works in a stand-alone WPF application. 谈到这一点,但似乎文章正在接近WPF方面的内容,但我真的不想对WPF控件进行更改,因为一切都在独立的WPF应用程序中运行。

If the only way to accomplish this is to make changes on the WPF side, I can get those changes made (I'm not responsible for the WPF control library but the person that is also works for the same company so it's not a problem other than getting his time to make the changes.) but I'm hoping for something I can do on the WinForms side to get this working. 如果实现这一目标的唯一方法是在WPF端进行更改,我可以进行这些更改(我不负责WPF控件库,但是那个也适用于同一家公司的人,所以这不是问题其他而不是花时间去做这些改变。)但是我希望能在WinForms方面做些什么才能让它发挥作用。

The WPF control library has a resource dictionary file named "Default.xaml" defined in the project with the following properties: WPF控件库在项目中定义了一个名为“Default.xaml”的资源字典文件,其中包含以下属性:

Build Action: Page Copy to Output Directory: Do not copy Custom Tool: MSBuild:Compile 构建操作:页面复制到输出目录:不要复制自定义工具:MSBuild:编译

The stand-alone WPF application has the following entry in it's App.xaml file: 独立的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>

It seems like the control library should already know how to get its resources. 似乎控制库应该已经知道如何获取其资源。 Using the Resources.MergedDictionaries.Add() seems like it should work, but where do I get the instance of the existing dictionary? 使用Resources.MergedDictionaries.Add()似乎应该可以工作,但是我从哪里获得现有字典的实例?

Assuming you know what resources you need (sounds like you do), you should just be able to "inject" them yourself. 假设你知道你需要什么资源(听起来像你这样做),你应该能够自己“注入”它们。 Something like: 就像是:

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

In your question you mention that there are existing resource dictionaries in the control library. 在您的问题中,您提到控件库中存在现有的资源字典。 If so, you can just do this: 如果是这样,你可以这样做:

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

For loading resource dictionaries that are embedded into the assembly, I've used the following snippet for loading them during the runtime: 为了加载嵌入到程序集中的资源字典,我在运行时使用了以下代码片段来加载它们:

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

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

This would also work for loading a dictionary in the executable directory. 这也适用于在可执行文件目录中加载字典。

Supposing you have your styles / templates / resources divided into many files Resources1.xaml and Resources2.xaml you can aggregate them into a single resource dictionary ( AllResources.xaml ). 假设您将样式/模板/资源分成许多文件Resources1.xamlResources2.xaml您可以将它们聚合到单个资源字典( AllResources.xaml )中。 A resource dictionary can be easily added to a control in control's xaml file. 资源字典可以轻松添加到控件的xaml文件中的控件中。 See the example below. 请参阅下面的示例。

(!) Set Resources1.xaml , Resources2.xaml and AllResources.xaml build actions to Page (!)Resources1.xamlResources2.xamlAllResources.xaml构建操作设置为Page

Resources1.xaml 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 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

Add resource dictionaries sources as relative paths to the 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>

Finally in your UserControl 最后在你的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>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM