0

在今晚解决一个围绕动态资源的问题时,我最终得到了一个依赖于Behavior类参与其相关框架元素的资源层次结构的能力的解决方案。例如,考虑以下

<Application>
    <Application.Resources>
        <system:String x:Key="TestString">In App Resources</system:String>
    </Application.Resources>

</Application>
<Window>
    <Window.Resources>
        <system:String x:Key="TestString">In Window Resources/system:String>
    </Window.Resources>

    <Border>
       <Border.Resources>
            <system:String x:Key="TestString">In Border Resources</system:String>
       </Border.Resources>

       <TextBlock Text="{DynamicResource TestString}" />

    </Border>

</Window>

TextBlock 将显示来自边框的资源。但是,如果我这样做...

public void Test()
{
    var frameworkElement = new FrameworkElement();
    var testString = (string)frameworkElement.FindResource("TestString");
}

...它从应用程序中找到一个,因为它不是可视树的一部分。

也就是说,如果我改为这样做......

public class MyBehavior : Behavior<FrameworkElement>
{
    public string Value... // Implement this as a DependencyProperty
}

然后像这样将它添加到 TextBlock ...

<TextBlock Text="{DynamicResource TestString}">
    <i:Interaction.Behaviors>
        <local:MyBehavior Value="{DynamicResource TestString}" />
    </i:Interaction.Behaviors>
</TextBlock>

该行为确实获得了资源的价值,并将动态跟踪它。但是怎么做?

行为不是 FrameworkElement,因此您不能对其调用 SetResourceReference,它也不是可视树的一部分,因此即使您可以调用 SetResourceReference,它仍然无法找到 FrameworkElement 本地的资源。然而,这正是 Behavior 所做的。如何?

换句话说,如果我们想编写我们自己的类来展示同样的行为(不是双关语),如何将自己插入到可视化树的资源层次结构中?

4

1 回答 1

0

好吧,我想我找到了!秘密是可冻结的。简而言之,当您将 Freezable 添加到 FrameworkElement 的资源时,该 Freezable 上分配有 DynamicResource 的任何 DependencyProperties 都将正确解析。

使用这些知识,我创建了一个 DynamicResourceBinding,让您可以像使用任何其他 DynamicResource 一样使用它,但具有能够指定转换器、格式字符串等的额外优势。

这是 StackOverflow 上该页面的链接,我在其中为动态和静态资源执行此操作...

帖子 33816511:如何创建 DynamicResourceBinding

于 2015-11-20T00:00:06.927 回答