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

发布于 2024-07-14 00:31:58 字数 1433 浏览 7 评论 0原文

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

一旦发生这种情况,我就会收到一堆如下所示的错误:

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

我发现了一个 参考链接因存档而失效这个可能与最初引用的同一篇文章)。 谈到了这一点,但看起来这篇文章更多地是从 WPF 方面来处理问题,但我真的不想对 WPF 控件进行更改,因为一切都在独立的 WPF 应用程序中运行。

如果实现此目的的唯一方法是在 WPF 端进行更改,我可以进行这些更改(我不负责 WPF 控件库,但也为同一家公司工作,所以这不是问题)而不是让他有时间进行更改。)但我希望我可以在 WinForms 方面做一些事情来使其正常工作。

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

构建操作:页面 复制到输出目录:不复制 自定义工具:MSBuild:Compile

独立的 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() 似乎应该可以工作,但是我在哪里可以获得现有字典的实例?

I have a Windows Forms application that needs to host a WPF control at runtime. 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. (The WPF control and all of it's resource dictionaries are all defined in the same WPF Control Library 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.

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.

The WPF control library has a resource dictionary file named "Default.xaml" defined in the project with the following properties:

Build Action: Page
Copy to Output Directory: Do not copy
Custom Tool: MSBuild:Compile

The stand-alone WPF application has the following entry in it's App.xaml file:

    <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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

风尘浪孓 2024-07-21 00:31:59

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

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

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

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

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.

情定在深秋 2024-07-21 00:31:59

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

(!)Resources1.xamlResources2.xamlAllResources.xaml 构建操作设置为 < code>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>

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). A resource dictionary can be easily added to a control in control's xaml file. See the example below.

(!) Set Resources1.xaml, Resources2.xaml and AllResources.xaml build actions to 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

Add resource dictionaries sources as relative paths to the 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.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>
生死何惧 2024-07-21 00:31:58

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

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

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

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

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;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文