首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如果目标不是FrameworkElement,如何在代码隐藏中设置DynamicResource?

如果目标不是FrameworkElement,如何在代码隐藏中设置DynamicResource?
EN

Stack Overflow用户
提问于 2018-09-03 16:15:35
回答 2查看 524关注 0票数 0

考虑一下这个BindingProxy类,它是Freezable的子类(因此,当添加到FrameworkElementResources集合中时,它会参与资源层次结构的查找)……

代码语言:javascript
运行
复制
public class BindingProxy : Freezable {

    public BindingProxy(){}
    public BindingProxy(object value)
        => Value = value;

    protected override Freezable CreateInstanceCore()
        => new BindingProxy();

    #region Value Property

        public static readonly DependencyProperty ValueProperty = DependencyProperty.Register(
            nameof(Value),
            typeof(object),
            typeof(BindingProxy),
            new FrameworkPropertyMetadata(default));

        public object Value {
            get => GetValue(ValueProperty);
            set => SetValue(ValueProperty, value);
        }

    #endregion Value Property
}

将它添加到您的XAML中,如下所示...

代码语言:javascript
运行
复制
<Window.Resources>
    <is:BindingProxy x:Key="TestValueProxy" Value="{DynamicResource TestValue}" />
</Window.Resources>

正如您所看到的,Value被设置为DynamicResource,因此它将自动跟踪由该键定义的资源的更改,正如预期的那样。

现在,如果您希望在代码隐藏中而不是在XAML中设置DynamicResource,如果目标对象是FrameworkElement,则只需对其调用SetResourceReference,如下所示...

代码语言:javascript
运行
复制
myTextBlock.SetResourceReference(TextBlock.TextProperty, "MyTextResource")

但是,SetResourceReference仅适用于FrameworkElement对象,而不适用于Freezable,因此您不能在BindingProxy上使用它。

深入研究FrameworkElement.SetResourceReference的源代码,您会发现...

代码语言:javascript
运行
复制
public void SetResourceReference(DependencyProperty dp, object name){
    base.SetValue(dp, new ResourceReferenceExpression(name));
    HasResourceReference = true;
}

不幸的是,ResourceReferenceExpression--它是如何工作的“肉”--是内部的,所以我也不能了解它。

那么,在代码隐藏中,如何在Freezable-based对象上设置DynamicResource来镜像我在XAML中可以做的事情呢?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-09-04 00:24:07

您可以在代码中使用DynamicResourceExtension实例:

代码语言:javascript
运行
复制
var proxy = new BindingProxy();
var dynamicResourceExtension = new DynamicResourceExtension("TestValue");
proxy.Value = dynamicResourceExtension.ProvideValue(null);

如果您看到代码引用here,您将看到ProvideValueserviceProvider为null时返回ResourceReferenceExpression。几乎和SetResourceReference做的事情一样

票数 1
EN

Stack Overflow用户

发布于 2018-09-03 23:53:46

使用反射创建ResourceReferenceExpression

代码语言:javascript
运行
复制
Type type = typeof(System.Windows.Window).Assembly.GetType("System.Windows.ResourceReferenceExpression");
ConstructorInfo ctor = type.GetConstructors()[0];
object resourceReferenceExpression = ctor.Invoke(new object[] { "TestValue" });
TestValueProxy.SetValue(BindingProxy.ValueProperty, resourceReferenceExpression);

显然,如果内部类型发生更改,此代码可能会崩溃,但如果确实需要对Freezable的值动态应用DynamicResource,则没有其他方法可做。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52145711

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档