首页 文章

WPF StaticResource工作,DynamicResource没有

提问于
浏览
9

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

  • 创建包含样式(作品)的主题generic.xaml

  • 添加字典以在generic.xaml中合并以包含应用程序中使用的画笔(作品)

  • make brush有ComponentResourceKey键(有效)

  • make control使用画笔作为静态资源(作品)

  • 使控件使用画笔作为动态资源(不工作,资源跟踪源说同样多:System.Windows.ResourceDictionary警告:9:找不到资源;)

  • 在App.Resources中动态添加具有相同键的画笔(与动态资源一起使用,它会改变颜色,不能像预期的那样使用静态资源)

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

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

有人可以帮帮我吗? :(

3 回答

  • 1

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

    • 有一个资源类将ComponentResourceKeys保存为静态属性 . 资源键的构造函数中使用的类型是此类的类型 . 这是在Resources程序集中 .

    • 在另一个程序集中有一个自定义控件的主题,即Controls程序集,它定义了一些使用资源类属性作为键的画笔:{x:Static Namespace:ResourceClass.ResourceKeyProperty}

    • 在同一主题中,控件模板使用画笔作为动态资源:{DynamicResource {x:Static Namespace:ResourceClass.ResourceKeyProperty}}

    • 还有一个应用程序使用这些控件,并在应用程序资源中动态添加自定义画笔 . 这些画笔具有与主题中相同的键 .

    最终结果是:

    • 控件最初不使用画笔

    • 控件确实使用应用程序资源中添加的画笔

    • 如果在主题中使用了StaticResource,控件最初会使用画笔,但是会忽略应用程序资源

    解决方案似乎是移动控件库中的资源类 .

    由于我仍然不知道为什么会这样,这个问题仍然是开放的,即使稍有改变:为什么它不适用于第一种情况?

  • 5

    这是区别,

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

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

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

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

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

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

    Summary: StaticResource必须在词典之前在编译时在同一文件中可用,资源将在Application.Resources字典中可用,它仍然可以在逻辑树中找到但在编译时仅在相同的dll或相同的generic.xaml中找到 .

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

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

  • 4

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

    因此,我将描述不工作,而不是描述解决方案repro设置 .

    解决方案

    目标框架: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

相关问题