【问题标题】:Loading/Using Resource Dictionaries from a WinForms hosted WPF control从 WinForms 托管的 WPF 控件加载/使用资源字典
【发布时间】:2009-02-23 21:33:52
【问题描述】:

我有一个需要在运行时承载 WPF 控件的 Windows 窗体应用程序。我已经完成了基本的托管和交互(使用 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: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() 似乎应该可以,但是我在哪里可以获得现有字典的实例?

【问题讨论】:

    标签: wpf winforms interop resources elementhost


    【解决方案1】:

    假设你知道你需要什么资源(听起来像你),你应该能够自己“注入”它们。比如:

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

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

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

    【讨论】:

    • 调用 Add 时的“键”和“值”从何而来?
    • 这更有意义,但字典不应该已经合并了吗?我更新了我的问题,提供了有关 WPF 方面外观的更多信息。
    • 你被震撼了,它神奇地起作用了。你真的节省了我的时间。
    • 但是你想在哪里运行这段代码呢? WPF 窗口的构造函数?
    【解决方案2】:

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

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

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

    【讨论】:

      【解决方案3】:

      假设您将样式/模板/资源分为多个文件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.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>
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-05-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-09-03
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多