请考虑此BindingProxy类,它是Freezable的子类(因此,当添加到FrameworkElement
的{{1}}集合中时,它将参与资源层次结构查找)...
Resources
您可以像这样将其添加到XAML中...
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
}
如您所见,<Window.Resources>
<is:BindingProxy x:Key="TestValueProxy" Value="{DynamicResource TestValue}" />
</Window.Resources>
设置为Value
,因此它将按预期自动跟踪对由该键定义的资源的更改。
现在,如果您想在代码隐藏中设置DynamicResource
而不是XAML,如果目标对象是DynamicResource
,则只需在其上调用FrameworkElement
,就像这样...
SetResourceReference
但是,myTextBlock.SetResourceReference(TextBlock.TextProperty, "MyTextResource")
仅在SetResourceReference
个对象上可用,而在FrameworkElement
个对象上不可用,因此您不能在Freezable
上使用它。
浏览BindingProxy
的源代码,您会发现...
FrameworkElement.SetResourceReference
不幸的是,public void SetResourceReference(DependencyProperty dp, object name){
base.SetValue(dp, new ResourceReferenceExpression(name));
HasResourceReference = true;
}
是它的工作原理,它是内部的,所以我也无法做到这一点。
因此,在代码隐藏中,如何在基于ResourceReferenceExpression
的对象上设置DynamicResource
来反映在XAML中可以执行的操作?
答案 0 :(得分:0)
使用反射创建一个ResourceReferenceExpression
:
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);
很明显,如果内部类型发生更改,此代码可能会中断,但是如果您确实需要能够动态地将DynamicResource
应用于Freezable
的值,则您无能为力。
答案 1 :(得分:0)
您可以在代码中使用DynamicResourceExtension
实例:
var proxy = new BindingProxy();
var dynamicResourceExtension = new DynamicResourceExtension("TestValue");
proxy.Value = dynamicResourceExtension.ProvideValue(null);
如果您看到代码参考here,则您会看到ProvideValue
为空时ResourceReferenceExpression
返回serviceProvider
。与SetResourceReference
几乎一样