我在Application.xaml中定义了数百个画笔。这些是项目中多个用户控件的共享资源。它们都有图案键:ch_YSD,ch_HJU,ch_IYO ......
我尝试在datatemplate中使用这些画笔。在datatemplate中,我可以访问画笔键的可变部分,也就是在数据模板中,我可以将YSD,HJU,IYO等作为字符串。
如何从xaml绑定到特定的画笔资源?
目前我有这样的解决方案:在样式中使用数据触发器根据绑定字符串(键的可变部分)将所需属性设置为指定的画笔。 我对此解决方案不满意,因为Application.xaml中的画笔列表会经常增加。
我不确定是否应该使用代码,因为我想在Application.xaml中使用共享资源的内存节省优势。
答案 0 :(得分:2)
这是一种看似简单的任务,但实际上没有完美的解决方案(或者我没有找到它)。第一种方法是使用值转换器。但它不起作用!我们需要设置转换器无法正确完成的资源引用。所以,我认为正确的方式是附加行为。但是你应该知道限制:只能有一个属性来应用资源。也许你可以根据自己的要求避免这种限制。
附加行为允许您将具有指定命名的资源引用到指定的依赖项属性:
public static class BrushResourceKeyBehavior
{
#region ResourceKey Property
public static readonly DependencyProperty ResourceKeyProperty = DependencyProperty.RegisterAttached(
"ResourceKey", typeof(object), typeof(BrushResourceKeyBehavior),
new FrameworkPropertyMetadata(OnResourceKeyChanged));
public static object GetResourceKey(DependencyObject dependencyObject)
{
return dependencyObject.GetValue(ResourceKeyProperty);
}
public static void SetSource(DependencyObject dependencyObject, object value)
{
dependencyObject.SetValue(ResourceKeyProperty, value);
}
#endregion
#region TargetProperty Property
public static readonly DependencyProperty TargetPropertyProperty = DependencyProperty.RegisterAttached(
"TargetProperty", typeof(DependencyProperty), typeof(BrushResourceKeyBehavior),
new FrameworkPropertyMetadata(OnTargetPropertyChanged));
public static DependencyProperty GetTargetProperty(DependencyObject dependencyObject)
{
return (DependencyProperty)dependencyObject.GetValue(TargetPropertyProperty);
}
public static void SetTargetProperty(DependencyObject dependencyObject, DependencyProperty value)
{
dependencyObject.SetValue(TargetPropertyProperty, value);
}
#endregion
private static void OnResourceKeyChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
{
var targetProperty = GetTargetProperty(dependencyObject);
if (targetProperty != null)
{
if (e.NewValue == null)
{
dependencyObject.ClearValue(targetProperty);
}
else
{
SetResourceReference(dependencyObject, targetProperty);
}
}
}
private static void OnTargetPropertyChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
{
var oldValue = e.OldValue as DependencyProperty;
var newValue = e.NewValue as DependencyProperty;
if (oldValue != null)
{
dependencyObject.ClearValue(oldValue);
}
if (newValue != null)
{
SetResourceReference(dependencyObject, newValue);
}
}
private static void SetResourceReference(DependencyObject dependencyObject, DependencyProperty targetProperty)
{
var fe = dependencyObject as FrameworkElement;
if (fe != null)
{
fe.SetResourceReference(targetProperty, String.Format("ch_{0}", GetResourceKey(fe)));
}
else
{
var fce = dependencyObject as FrameworkContentElement;
if (fce != null)
{
fce.SetResourceReference(targetProperty, String.Format("ch_{0}", GetResourceKey(fce)));
}
}
}
}
行为可以在XAML中使用,如下所示:
<ItemsControl>
<Border local:BrushResourceKeyBehavior.Source="YSD"
local:BrushResourceKeyBehavior.TargetProperty="Border.Background"
Height="20"/>
<Border local:BrushResourceKeyBehavior.Source="HJU"
local:BrushResourceKeyBehavior.TargetProperty="Border.Background"
Height="20"/>
<Border local:BrushResourceKeyBehavior.Source="IYO"
local:BrushResourceKeyBehavior.TargetProperty="Border.Background"
Height="20"/>
</ItemsControl>
上面的代码相当于:
<ItemsControl>
<Border Background="{DynamicResource ch_YSD}"
Height="20"/>
<Border Background="{DynamicResource ch_HJU}"
Height="20"/>
<Border Background="{DynamicResource ch_IYO}"
Height="20"/>
</ItemsControl>