【问题标题】:Resources not resolving from ResourceDictionaries资源无法从 ResourceDictionaries 解析
【发布时间】:2013-02-04 10:54:16
【问题描述】:

我在从 ResourceDictionaries 解析资源时遇到问题。

我决定将我相当大的 ResourceDictionary 重构为单独的字典文件,并组织到子文件夹中。

我在 Resources 下有一个 ResourceLibrary.xaml:

<ResourceDictionary x:Class="MyProject.Resources.ResourceLibrary"
                xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
   <ResourceDictionary.MergedDictionaries>
     <!-- Colours -->
     <ResourceDictionary Source="Colors/ConnectedCellColor.xaml" />
     <!-- Brushes -->
     <ResourceDictionary Source="Brushes/ConnectorCellBrush.xaml" />
     <!-- Control Templates -->
     <ResourceDictionary Source="ControlTemplates/ConnectorCellTemplate.xaml" />
     <!-- Base Styles -->
     <ResourceDictionary Source="BaseStyles/ConnectorBaseStyle.xaml" />
   </ResourceDictionary.MergedDictionaries>
</ResourceDictionary>

类的存在是有原因的,在后面的代码中,我可以添加 [Export(typeof (ResourceDictionary))] 以便 MEF 可以找到它。

我有一个观点:(简体)

<UserControl x:Class="MyProject.ConnectorCellView"
         Style="{StaticResource ConnectorBaseStyle}"
</UserControl>

连接器基础样式:

<ResourceDictionary>
   <Style x:Key="ConnectorBaseStyle" TargetType="UserControl">
      <Setter Property="Template" Value="{StaticResource ConnectorCellTemplate}" />
   </Style>
</ResourceDictionary>

模板有 StaticResources 来尝试获取画笔和颜色。

所有这些 StaticResources 将不再解析。

我认为这可能是一个订单问题,但由于这些资源包含在我的主程序的插件中,我使用 MEF 和 ImportMany 来获取所有导出的 ResourceDictionaries,并在我的 Caliburn.Micro 引导程序中:

  public void OnImportsSatisfied()
  {
     foreach (ResourceDictionary resourceDictionary in ResourceDictionaries)
     {
        Application.Resources.MergedDictionaries.Add(resourceDictionary);
     }
  }

(我在某处发现的巧妙技巧)

我实际上可以运行我的程序,当创建该视图时,它会在尝试设置样式时抛出异常:

System.InvalidCastException
无法将类型为“MS.Internal.NamedObject”的对象转换为类型 System.Windows.FrameworkTemplate”。

我发现与此相关的唯一信息与定义的订单资源有关,但从我在 ResourceLibrary 中的订单来看,它应该可以工作。

当抛出异常时,我可以检查 Application.Current.Resources.MergedDictionaries, 并查看资源。

我尝试了多种在 ResourceLibrary 中指定 Source 的方法

<ResourceDictionary Source="/MyProject;component/Resources/BaseStyles/ConnectorBaseStyle.xaml" />

等,对找到它们没有影响。这些资源仅供插件代码使用。

似乎唯一可行的方法是将所有 StaticResources 更改为 DynamicResources

这对我来说没有意义,如果是订单问题,当它们都在同一个文件中时,为什么静态会起作用?

我的一些样式使用了 BasedOn,它们不适用于 DynamicResource。

你能帮我理解为什么会发生这种情况,以及如何让它发挥作用吗?

【问题讨论】:

    标签: wpf xaml resourcedictionary


    【解决方案1】:

    这是一个排序问题,但与您的合并顺序无关 - 它与加载顺序有关。这基本上是加载 ResourceLibrary 字典时发生的情况:

    1. ConnectedCellColor 实例化
    2. ConnectedCellColor 加载到 ResourceLibrary
    3. ConnectorCellBrush 实例化
    4. ConnectorCellBrush 加载到 ResourceLibrary
    5. ConnectorCellTemplate 实例化
    6. ConnectorCellTemplate 加载到 ResourceLibrary
    7. ConnectorBaseStyle 实例化
    8. ConnectorBaseStyle 加载到 ResourceLibrary

    这里的问题是,以前您的单个文件只有一个实例化步骤,现在您将其分解为多个步骤,每个步骤都是独立发生的。当实例化 ConnectorBaseStyle 时,ConnectorCellTemplate 已加载,但此时 ConnectorBaseStyle 不知道 ResourceLibrary 的内容。使用 DynamicResource 这不是问题,因为这些引用可以在第 8 步解决,但 StaticResource 需要在第 7 步立即解决。

    最简单的解决方法是尽可能使用Dynamic。对于需要Static(如BasedOn)的地方,您需要保证资源在实例化期间可用,例如,将ConnectorCellTemplate 合并到ConnectorBaseStyle 中,或者将所需的所有内容合并到App.xaml 中,即可用于一切。当您获得更多文件并合并到多个位置时,这会使事情变得复杂且难以管理,但至少资源系统足够智能以识别重复项,因此在上述情况下,您仍然只会获得一个 ConnectorCellTemplate 实例,即使它正在两个地方合并。

    【讨论】:

    • 不确定我是否完全理解这一点。据我所知,ResourceLibrary 是在我的应用程序初始化后加载的,因为我可以在调试器中看到资源。创建视图后,在我看来,如果 BaseStyle 在应用程序的资源中,它应该解决...
    猜你喜欢
    • 2019-03-06
    • 1970-01-01
    • 1970-01-01
    • 2015-04-30
    • 1970-01-01
    • 1970-01-01
    • 2014-09-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多