これは単純に見える一種のタスクですが、実際には完璧な解決策はありません(または私はそれを見つけられませんでした)。最初のアプローチは、値コンバーターを使用することです。しかし、それは機能しません!コンバーターでは正しく実行できないリソース参照を設定する必要があります。ですから、正しい方法は付随する行動だと思います。ただし、制限について知っておく必要があります。リソースを適用できるプロパティは1つだけです。要件によっては、この制限を回避できる可能性があります。
アタッチされた動作により、指定された依存関係プロパティに指定された名前のリソースを参照できます。
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>