ComponentResourceKey 作为 DynamicResource 问题

发布于 2024-08-08 11:04:11 字数 9301 浏览 1 评论 0原文

我在使用 ComponentResourceKey 时发现一些意外行为。出现问题是因为我使用了 SystemColors 类中使用的名称。

考虑以下代码:

首先,我将 a 中的 ComponentResourceKey 公开为静态属性:


public enum ColorKeys
{
    ControlColor
}

public class MyColors
{
    public static ComponentResourceKey ControlColorKey
    {
        get 
        { 
            return new ComponentResourceKey(typeof(MyColors), ColorKeys.ControlColor); 
        }
    }
}

使用标记中的键将资源分配给该键是可行的。使用 ComponentResourceKey 标记将该资源作为 DynamicResource 调用是可行的。但使用静态属性调用同一资源将解析为 SystemColors.ControlColorKey 资源。

这是 xaml:

<Window.Resources>
    <Color x:Key="{x:Static l:MyColors.ControlColorKey}">#FF0000FF</Color>
    <SolidColorBrush x:Key="UsingVerbose" 
                     Color="{DynamicResource {ComponentResourceKey TypeInTargetAssembly={x:Type l:MyColors}, 
                                ResourceId={x:Static l:ColorKeys.ControlColor}}}"/>
    <SolidColorBrush x:Key="UsingStatic" 
                     Color="{DynamicResource {x:Static l:MyColors.ControlColorKey}}"/>                
</Window.Resources>
<Grid>
    <StackPanel>
        <Button Height="20" Width="80" Background="{DynamicResource UsingVerbose}" Content="Verbose"/>
        <Button Height="20" Width="80" Background="{DynamicResource UsingStatic}" Content="Static"/>
    </StackPanel>
</Grid>

显示窗口时,“详细”按钮正确显示蓝色背景。但下方的“静态”按钮显示 SystemColors.ControlColorKey 颜色。

将静态属性的名称更改为另一个名称可以使两个画笔解析为正确的颜色。

但我不确定为什么 DynamicResource 对于密钥的静态实例和由标记实例化的实例的解析方式不同?

谢谢,

K

PS:这是 ResourceDictionarySource 的相关跟踪输出

System.Windows.ResourceDictionary Start: 10 : New resource dictionary set; Owner='TestMergedDictionaries.Window1'; Owner.HashCode='64923656'; Owner.Type='TestMergedDictionaries.Window1'; OldDictionary='0'; NewDictionary='System.Windows.ResourceDictionary'; NewDictionary.HashCode='44624228'; NewDictionary.Type='System.Windows.ResourceDictionary'
System.Windows.ResourceDictionary Stop: 10 : 
System.Windows.ResourceDictionary Start: 12 : Deferred resource has been added to ResourceDictionary; Dictionary='System.Windows.ResourceDictionary'; Dictionary.HashCode='44624228'; Dictionary.Type='System.Windows.ResourceDictionary'; ResourceKey='TargetType=TestMergedDictionaries.MyColors ID=ControlColor'; ResourceKey.HashCode='1936592'; ResourceKey.Type='System.Windows.ComponentResourceKey'
System.Windows.ResourceDictionary Stop: 12 : 
System.Windows.ResourceDictionary Start: 12 : Deferred resource has been added to ResourceDictionary; Dictionary='System.Windows.ResourceDictionary'; Dictionary.HashCode='44624228'; Dictionary.Type='System.Windows.ResourceDictionary'; ResourceKey='UsingVerbose'
System.Windows.ResourceDictionary Stop: 12 : 
System.Windows.ResourceDictionary Start: 12 : Deferred resource has been added to ResourceDictionary; Dictionary='System.Windows.ResourceDictionary'; Dictionary.HashCode='44624228'; Dictionary.Type='System.Windows.ResourceDictionary'; ResourceKey='UsingStatic'
System.Windows.ResourceDictionary Stop: 12 : 
System.Windows.ResourceDictionary Start: 11 : Searching for resource; Element='System.Windows.Controls.Button'; Element.HashCode='52727599'; Element.Type='System.Windows.Controls.Button'; ResourceKey='UsingVerbose'
System.Windows.ResourceDictionary Start: 3 : Found resource item on an element; Element='TestMergedDictionaries.Window1'; Element.HashCode='64923656'; Element.Type='TestMergedDictionaries.Window1'; ResourceKey='UsingVerbose'; Value='System.Windows.DeferredResourceReference'; Value.HashCode='14347911'; Value.Type='System.Windows.DeferredResourceReference'
System.Windows.ResourceDictionary Stop: 3 : 
System.Windows.ResourceDictionary Stop: 11 : Searching for resource; Element='System.Windows.Controls.Button'; Element.HashCode='52727599'; Element.Type='System.Windows.Controls.Button'; ResourceKey='UsingVerbose'

... removed uninteresting traces ...

System.Windows.ResourceDictionary Start: 11 : Searching for resource; Element='TestMergedDictionaries.Window1'; Element.HashCode='64923656'; Element.Type='TestMergedDictionaries.Window1'; ResourceKey='TargetType=TestMergedDictionaries.MyColors ID=ControlColor'; ResourceKey.HashCode='1936592'; ResourceKey.Type='System.Windows.ComponentResourceKey'
System.Windows.ResourceDictionary Start: 3 : Found resource item on an element; Element='TestMergedDictionaries.Window1'; Element.HashCode='64923656'; Element.Type='TestMergedDictionaries.Window1'; ResourceKey='TargetType=TestMergedDictionaries.MyColors ID=ControlColor'; ResourceKey.HashCode='1936592'; ResourceKey.Type='System.Windows.ComponentResourceKey'; Value='System.Windows.DeferredResourceReference'; Value.HashCode='23488915'; Value.Type='System.Windows.DeferredResourceReference'
System.Windows.ResourceDictionary Stop: 3 : 
System.Windows.ResourceDictionary Stop: 11 : Searching for resource; Element='TestMergedDictionaries.Window1'; Element.HashCode='64923656'; Element.Type='TestMergedDictionaries.Window1'; ResourceKey='TargetType=TestMergedDictionaries.MyColors ID=ControlColor'; ResourceKey.HashCode='1936592'; ResourceKey.Type='System.Windows.ComponentResourceKey'

System.Windows.ResourceDictionary Start: 2 : Delayed creation of resource; Dictionary='System.Windows.ResourceDictionary'; Dictionary.HashCode='23264094'; Dictionary.Type='System.Windows.ResourceDictionary'; ResourceKey='System.Windows.Controls.TextBlock'; Value='DefAttributeKeyType typeId=TextBlock'; Value.HashCode='23521433'; Value.Type='System.Windows.Markup.BamlDefAttributeKeyTypeRecord'
System.Windows.ResourceDictionary Stop: 2 : Delayed creation of resource; Dictionary='System.Windows.ResourceDictionary'; Dictionary.HashCode='23264094'; Dictionary.Type='System.Windows.ResourceDictionary'; ResourceKey='System.Windows.Controls.TextBlock'; Value='System.Windows.Style'; Value.HashCode='5'; Value.Type='System.Windows.Style'

System.Windows.ResourceDictionary Start: 2 : Delayed creation of resource; Dictionary='System.Windows.ResourceDictionary'; Dictionary.HashCode='44624228'; Dictionary.Type='System.Windows.ResourceDictionary'; ResourceKey='UsingStatic'; Value='DefAttributeKeyString'; Value.HashCode='24854661'; Value.Type='System.Windows.Markup.BamlDefAttributeKeyStringRecord'
System.Windows.ResourceDictionary Start: 11 : Searching for resource; Element=''; ResourceKey='ControlColor'; ResourceKey.HashCode='35'; ResourceKey.Type='System.Windows.SystemResourceKey'
System.Windows.ResourceDictionary Start: 8 : Found resource item in theme; Dictionary='System.Windows.SystemResourceHost'; Dictionary.HashCode='65273341'; Dictionary.Type='System.Windows.SystemResourceHost'; ResourceKey='ControlColor'; ResourceKey.HashCode='35'; ResourceKey.Type='System.Windows.SystemResourceKey'; Value='#FFF0F0F0'
System.Windows.ResourceDictionary Stop: 8 : 
System.Windows.ResourceDictionary Stop: 11 : Searching for resource; Element=''; ResourceKey='ControlColor'; ResourceKey.HashCode='35'; ResourceKey.Type='System.Windows.SystemResourceKey'
System.Windows.ResourceDictionary Stop: 2 : Delayed creation of resource; Dictionary='System.Windows.ResourceDictionary'; Dictionary.HashCode='44624228'; Dictionary.Type='System.Windows.ResourceDictionary'; ResourceKey='UsingStatic'; Value='#FFF0F0F0'; Value.HashCode='12408161'; Value.Type='System.Windows.Media.SolidColorBrush'

System.Windows.ResourceDictionary Start: 11 : Searching for resource; Element='TestMergedDictionaries.Window1'; Element.HashCode='64923656'; Element.Type='TestMergedDictionaries.Window1'; ResourceKey='ControlColor'; ResourceKey.HashCode='35'; ResourceKey.Type='System.Windows.SystemResourceKey'
System.Windows.ResourceDictionary Start: 8 : Found resource item in theme; Dictionary='System.Windows.SystemResourceHost'; Dictionary.HashCode='65273341'; Dictionary.Type='System.Windows.SystemResourceHost'; ResourceKey='ControlColor'; ResourceKey.HashCode='35'; ResourceKey.Type='System.Windows.SystemResourceKey'; Value='#FFF0F0F0'
System.Windows.ResourceDictionary Stop: 8 : 
System.Windows.ResourceDictionary Stop: 11 : Searching for resource; Element='TestMergedDictionaries.Window1'; Element.HashCode='64923656'; Element.Type='TestMergedDictionaries.Window1'; ResourceKey='ControlColor'; ResourceKey.HashCode='35'; ResourceKey.Type='System.Windows.SystemResourceKey'

System.Windows.ResourceDictionary Start: 2 : Delayed creation of resource; Dictionary='System.Windows.ResourceDictionary'; Dictionary.HashCode='44624228'; Dictionary.Type='System.Windows.ResourceDictionary'; ResourceKey='TargetType=TestMergedDictionaries.MyColors ID=ControlColor'; ResourceKey.HashCode='1936592'; ResourceKey.Type='System.Windows.ComponentResourceKey'; Value='KeyElementStart typeId=StaticExtension'; Value.HashCode='54371668'; Value.Type='System.Windows.Markup.BamlKeyElementStartRecord'
System.Windows.ResourceDictionary Stop: 2 : Delayed creation of resource; Dictionary='System.Windows.ResourceDictionary'; Dictionary.HashCode='44624228'; Dictionary.Type='System.Windows.ResourceDictionary'; ResourceKey='TargetType=TestMergedDictionaries.MyColors ID=ControlColor'; ResourceKey.HashCode='1936592'; ResourceKey.Type='System.Windows.ComponentResourceKey'; Value='#FF0000FF'

I'm seeing some unexpected behavior using ComponentResourceKey. The problem came up because I was using names used in the SystemColors class.

Consider the following code:

First I expose a ComponentResourceKey in a as a static property:


public enum ColorKeys
{
    ControlColor
}

public class MyColors
{
    public static ComponentResourceKey ControlColorKey
    {
        get 
        { 
            return new ComponentResourceKey(typeof(MyColors), ColorKeys.ControlColor); 
        }
    }
}

Using the key in markup to assign a resource to that key works. Invoking that resource as a DynamicResource with the ComponentResourceKey markup works. But Invoking that same resource using the static property resolves to the SystemColors.ControlColorKey resource.

Here is the xaml:

<Window.Resources>
    <Color x:Key="{x:Static l:MyColors.ControlColorKey}">#FF0000FF</Color>
    <SolidColorBrush x:Key="UsingVerbose" 
                     Color="{DynamicResource {ComponentResourceKey TypeInTargetAssembly={x:Type l:MyColors}, 
                                ResourceId={x:Static l:ColorKeys.ControlColor}}}"/>
    <SolidColorBrush x:Key="UsingStatic" 
                     Color="{DynamicResource {x:Static l:MyColors.ControlColorKey}}"/>                
</Window.Resources>
<Grid>
    <StackPanel>
        <Button Height="20" Width="80" Background="{DynamicResource UsingVerbose}" Content="Verbose"/>
        <Button Height="20" Width="80" Background="{DynamicResource UsingStatic}" Content="Static"/>
    </StackPanel>
</Grid>

When the window is shown, the "Verbose" button corretly displays a blue background. But the lower "Static" button shows the SystemColors.ControlColorKey color.

Changing the name of the static property to another name makes both brushes to resolve to the right color.

But I'm left feeling unsure of why is the DynamicResource resolving differently for the static instance of the key, and the one instantiated by markup?

Thanks,

K

PS: Here is the relevant trace output of the ResourceDictionarySource

System.Windows.ResourceDictionary Start: 10 : New resource dictionary set; Owner='TestMergedDictionaries.Window1'; Owner.HashCode='64923656'; Owner.Type='TestMergedDictionaries.Window1'; OldDictionary='0'; NewDictionary='System.Windows.ResourceDictionary'; NewDictionary.HashCode='44624228'; NewDictionary.Type='System.Windows.ResourceDictionary'
System.Windows.ResourceDictionary Stop: 10 : 
System.Windows.ResourceDictionary Start: 12 : Deferred resource has been added to ResourceDictionary; Dictionary='System.Windows.ResourceDictionary'; Dictionary.HashCode='44624228'; Dictionary.Type='System.Windows.ResourceDictionary'; ResourceKey='TargetType=TestMergedDictionaries.MyColors ID=ControlColor'; ResourceKey.HashCode='1936592'; ResourceKey.Type='System.Windows.ComponentResourceKey'
System.Windows.ResourceDictionary Stop: 12 : 
System.Windows.ResourceDictionary Start: 12 : Deferred resource has been added to ResourceDictionary; Dictionary='System.Windows.ResourceDictionary'; Dictionary.HashCode='44624228'; Dictionary.Type='System.Windows.ResourceDictionary'; ResourceKey='UsingVerbose'
System.Windows.ResourceDictionary Stop: 12 : 
System.Windows.ResourceDictionary Start: 12 : Deferred resource has been added to ResourceDictionary; Dictionary='System.Windows.ResourceDictionary'; Dictionary.HashCode='44624228'; Dictionary.Type='System.Windows.ResourceDictionary'; ResourceKey='UsingStatic'
System.Windows.ResourceDictionary Stop: 12 : 
System.Windows.ResourceDictionary Start: 11 : Searching for resource; Element='System.Windows.Controls.Button'; Element.HashCode='52727599'; Element.Type='System.Windows.Controls.Button'; ResourceKey='UsingVerbose'
System.Windows.ResourceDictionary Start: 3 : Found resource item on an element; Element='TestMergedDictionaries.Window1'; Element.HashCode='64923656'; Element.Type='TestMergedDictionaries.Window1'; ResourceKey='UsingVerbose'; Value='System.Windows.DeferredResourceReference'; Value.HashCode='14347911'; Value.Type='System.Windows.DeferredResourceReference'
System.Windows.ResourceDictionary Stop: 3 : 
System.Windows.ResourceDictionary Stop: 11 : Searching for resource; Element='System.Windows.Controls.Button'; Element.HashCode='52727599'; Element.Type='System.Windows.Controls.Button'; ResourceKey='UsingVerbose'

... removed uninteresting traces ...

System.Windows.ResourceDictionary Start: 11 : Searching for resource; Element='TestMergedDictionaries.Window1'; Element.HashCode='64923656'; Element.Type='TestMergedDictionaries.Window1'; ResourceKey='TargetType=TestMergedDictionaries.MyColors ID=ControlColor'; ResourceKey.HashCode='1936592'; ResourceKey.Type='System.Windows.ComponentResourceKey'
System.Windows.ResourceDictionary Start: 3 : Found resource item on an element; Element='TestMergedDictionaries.Window1'; Element.HashCode='64923656'; Element.Type='TestMergedDictionaries.Window1'; ResourceKey='TargetType=TestMergedDictionaries.MyColors ID=ControlColor'; ResourceKey.HashCode='1936592'; ResourceKey.Type='System.Windows.ComponentResourceKey'; Value='System.Windows.DeferredResourceReference'; Value.HashCode='23488915'; Value.Type='System.Windows.DeferredResourceReference'
System.Windows.ResourceDictionary Stop: 3 : 
System.Windows.ResourceDictionary Stop: 11 : Searching for resource; Element='TestMergedDictionaries.Window1'; Element.HashCode='64923656'; Element.Type='TestMergedDictionaries.Window1'; ResourceKey='TargetType=TestMergedDictionaries.MyColors ID=ControlColor'; ResourceKey.HashCode='1936592'; ResourceKey.Type='System.Windows.ComponentResourceKey'

System.Windows.ResourceDictionary Start: 2 : Delayed creation of resource; Dictionary='System.Windows.ResourceDictionary'; Dictionary.HashCode='23264094'; Dictionary.Type='System.Windows.ResourceDictionary'; ResourceKey='System.Windows.Controls.TextBlock'; Value='DefAttributeKeyType typeId=TextBlock'; Value.HashCode='23521433'; Value.Type='System.Windows.Markup.BamlDefAttributeKeyTypeRecord'
System.Windows.ResourceDictionary Stop: 2 : Delayed creation of resource; Dictionary='System.Windows.ResourceDictionary'; Dictionary.HashCode='23264094'; Dictionary.Type='System.Windows.ResourceDictionary'; ResourceKey='System.Windows.Controls.TextBlock'; Value='System.Windows.Style'; Value.HashCode='5'; Value.Type='System.Windows.Style'

System.Windows.ResourceDictionary Start: 2 : Delayed creation of resource; Dictionary='System.Windows.ResourceDictionary'; Dictionary.HashCode='44624228'; Dictionary.Type='System.Windows.ResourceDictionary'; ResourceKey='UsingStatic'; Value='DefAttributeKeyString'; Value.HashCode='24854661'; Value.Type='System.Windows.Markup.BamlDefAttributeKeyStringRecord'
System.Windows.ResourceDictionary Start: 11 : Searching for resource; Element=''; ResourceKey='ControlColor'; ResourceKey.HashCode='35'; ResourceKey.Type='System.Windows.SystemResourceKey'
System.Windows.ResourceDictionary Start: 8 : Found resource item in theme; Dictionary='System.Windows.SystemResourceHost'; Dictionary.HashCode='65273341'; Dictionary.Type='System.Windows.SystemResourceHost'; ResourceKey='ControlColor'; ResourceKey.HashCode='35'; ResourceKey.Type='System.Windows.SystemResourceKey'; Value='#FFF0F0F0'
System.Windows.ResourceDictionary Stop: 8 : 
System.Windows.ResourceDictionary Stop: 11 : Searching for resource; Element=''; ResourceKey='ControlColor'; ResourceKey.HashCode='35'; ResourceKey.Type='System.Windows.SystemResourceKey'
System.Windows.ResourceDictionary Stop: 2 : Delayed creation of resource; Dictionary='System.Windows.ResourceDictionary'; Dictionary.HashCode='44624228'; Dictionary.Type='System.Windows.ResourceDictionary'; ResourceKey='UsingStatic'; Value='#FFF0F0F0'; Value.HashCode='12408161'; Value.Type='System.Windows.Media.SolidColorBrush'

System.Windows.ResourceDictionary Start: 11 : Searching for resource; Element='TestMergedDictionaries.Window1'; Element.HashCode='64923656'; Element.Type='TestMergedDictionaries.Window1'; ResourceKey='ControlColor'; ResourceKey.HashCode='35'; ResourceKey.Type='System.Windows.SystemResourceKey'
System.Windows.ResourceDictionary Start: 8 : Found resource item in theme; Dictionary='System.Windows.SystemResourceHost'; Dictionary.HashCode='65273341'; Dictionary.Type='System.Windows.SystemResourceHost'; ResourceKey='ControlColor'; ResourceKey.HashCode='35'; ResourceKey.Type='System.Windows.SystemResourceKey'; Value='#FFF0F0F0'
System.Windows.ResourceDictionary Stop: 8 : 
System.Windows.ResourceDictionary Stop: 11 : Searching for resource; Element='TestMergedDictionaries.Window1'; Element.HashCode='64923656'; Element.Type='TestMergedDictionaries.Window1'; ResourceKey='ControlColor'; ResourceKey.HashCode='35'; ResourceKey.Type='System.Windows.SystemResourceKey'

System.Windows.ResourceDictionary Start: 2 : Delayed creation of resource; Dictionary='System.Windows.ResourceDictionary'; Dictionary.HashCode='44624228'; Dictionary.Type='System.Windows.ResourceDictionary'; ResourceKey='TargetType=TestMergedDictionaries.MyColors ID=ControlColor'; ResourceKey.HashCode='1936592'; ResourceKey.Type='System.Windows.ComponentResourceKey'; Value='KeyElementStart typeId=StaticExtension'; Value.HashCode='54371668'; Value.Type='System.Windows.Markup.BamlKeyElementStartRecord'
System.Windows.ResourceDictionary Stop: 2 : Delayed creation of resource; Dictionary='System.Windows.ResourceDictionary'; Dictionary.HashCode='44624228'; Dictionary.Type='System.Windows.ResourceDictionary'; ResourceKey='TargetType=TestMergedDictionaries.MyColors ID=ControlColor'; ResourceKey.HashCode='1936592'; ResourceKey.Type='System.Windows.ComponentResourceKey'; Value='#FF0000FF'

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

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

发布评论

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

评论(1

执笔绘流年 2024-08-15 11:04:11

在静态 ControlColorKey 中,每次访问 getter 时都会创建 ComponentResourceKey 的新实例。因此,第二次使用引用了不同的对象,并且没有获得更新的颜色。
如果将代码更改为简单的静态字段,它将按预期工作:

public static ComponentResourceKey ControlColorKey = new ComponentResourceKey(typeof(MyColors), ColorKeys.ControlColor);

In your static ControlColorKey, you are creating a new instance of the ComponentResourceKey every time the getter is accessed. Therefore the second usage references a different object and does not get the updated color.
If you change your code to a simple static field, it works as expected:

public static ComponentResourceKey ControlColorKey = new ComponentResourceKey(typeof(MyColors), ColorKeys.ControlColor);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文