WPF StaticResource工作,DynamicResource不工作

时间:2010-08-21 09:31:18

标签: wpf xaml themes dynamicresource componentresourcekey

我一直在尝试一天,无济于事,在主题中创建一堆画笔,然后在自定义控件中使用DynamicResource。我做的是这个:

  • 创建主题generic.xaml,其中包含样式(作品)
  • 添加字典以在generic.xaml中合并以包含应用程序中使用的画笔(作品)
  • 使画笔具有ComponentResourceKey键(可行)
  • 使控件使用画笔作为静态资源(工作)
  • 使控件使用画笔作为动态资源(不工作,资源跟踪源说的很多:System.Windows.ResourceDictionary警告:9:找不到资源;)
  • 使用相同的键动态地在App.Resources中添加一个画笔(使用动态资源,它会改变颜色,不能像预期的那样使用静态资源)

所以我的问题是我找不到任何方法来定义主题中的默认值,以便我可以在应用程序中以编程方式更改它们。 StaticResource如何找到画笔而不是DynamicResource?!

我必须补充一点,我创建了一个静态类,将组件资源键作为属性保存,然后我在xaml中使用{x:Static UI:ResourceScheme.ControlBackgroundKey}。我的问题似乎与此问题类似:ComponentResourceKey as DynamicResource problem只有当我将静态属性键替换为组件资源键的XAML标记时,它仍然不起作用。

有人可以帮帮我吗? :(

3 个答案:

答案 0 :(得分:5)

最后修好了。看来,在另一个程序集中使用组件资源键的类型会导致整个问题。让我总结一下:

  • 有一个资源类将ComponentResourceKeys保存为静态属性。资源键的构造函数中使用的类型是此类的类型。这是在资源组件中。
  • 在另一个程序集中有一个自定义控件的主题,即Controls程序集,它定义了一些使用资源类属性作为键的画笔:{x:Static Namespace:ResourceClass.ResourceKeyProperty}
  • 在同一主题中,控件模板使用画笔作为动态资源:{DynamicResource {x:Static Namespace:ResourceClass.ResourceKeyProperty}}
  • 还有一个应用程序使用这些控件并在应用程序资源中动态添加自定义画笔。这些画笔与主题中的画笔具有相同的键。

最终结果是:

  • 控件最初不使用画笔
  • 控件确实使用了在应用程序资源中添加的画笔
  • 如果在主题中使用StaticResource,则控件最初使用画笔,但忽略应用程序资源

解决方法似乎是在控件库中移动资源类。

由于我仍然不知道为什么会发生这种情况,这个问题仍然存在,即使稍有改变:为什么它在第一种情况下不起作用?

答案 1 :(得分:4)

这是差异,

在加载时加载StaticResource,这意味着您使用的资源键必须在使用前进行词法定义。

因此,必须在同一generic.xaml文件中的控件定义之上定义自定义控件的静态资源。因此,如果你将画笔放在不同的xaml中,那么在静态资源的情况下它肯定不会起作用。

这是原因,除非xaml类型的其他资源在同一文件中的complile中以某种形式包含的形式包含,否则不能在文件中使用静态资源。它只是意味着文件/组件/控件的实际xaml应该如何包含您使用的静态资源的实际引用。

现在我怀疑为什么DynamicResource不起作用,这是因为DynamicResource可能只会查看Application(使用控件的地方)ResourceDictionary而不是generic.xaml。

我不是100%肯定,但我觉得如果你定义一个自定义控件,如果你使用DynamicResource,那么你的资源必须在应用程序的资源字典或控件的资源字典的父容器中,但它不能在generic.xaml。

因为DynamicResource只会查找控件运行时逻辑树中的键,这就是为什么它可能找不到generic.xaml中的资源,除非在Application.Resources中明确添加了generic.xaml。

<强>要点: StaticResource必须在编译时在同一个文件中以词法形式提供,资源将在Application.Resources字典中可用,它仍然可以在逻辑树中找到但在编译时只能在相同的dll或相同的generic.xaml中找到。

DynamicResource必须在Application.Resources中搜索,并在运行时在控件的逻辑树中搜索。

如需更多参考,请查看Resources Overview

答案 2 :(得分:1)

我试图重现你的问题来测试一些关于它为什么不起作用的理论,但是我无法重现这个问题。设置似乎有效。

因此,我将描述非工作复制设置,而不是描述解决方案。

解决方案

目标框架:4.6

项目

  • 控制
    • 的引用
      • 资源
    • 文件
      • Theme.xaml
  • 资源
    • 文件
      • Keys.cs
  • WpfApplication
    • 的引用
      • 控制
      • 资源
    • 文件
      • MainWindow.xaml

文件内容

Theme.xaml

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:r="clr-namespace:Resources;assembly=Resources">
    <Color x:Key="{x:Static r:Keys.PrettyColor}">Red</Color>
    <SolidColorBrush x:Key="{x:Static r:Keys.PrettyBrush}" 
                     Color="{DynamicResource {x:Static r:Keys.PrettyColor}}" />
</ResourceDictionary>

Keys.cs

namespace Resources {
    using System.Windows;

    public static class Keys {
        public static readonly ComponentResourceKey PrettyBrush =
            new ComponentResourceKey(typeof(Keys), Ids.PrettyBrush);

        public static readonly ComponentResourceKey PrettyColor =
            new ComponentResourceKey(typeof(Keys), Ids.PrettyColor);
    }

    public static class Ids {
        public const string PrettyBrush = "PrettyBrush";
        public const string PrettyColor = "PrettyColor";
    }
}

MainWindow.xaml

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:resources="clr-namespace:Resources;assembly=Resources"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="/Controls;component/Theme.xaml" />
            </ResourceDictionary.MergedDictionaries>
            <Color x:Key="{x:Static resources:Keys.PrettyColor}">Blue</Color>
        </ResourceDictionary>
    </Window.Resources>
    <Border Background="{DynamicResource {x:Static resources:Keys.PrettyBrush}}" />
</Window>

对于懒人来说,这是一个截图:

enter image description here