2012-04-08 20 views
1

私はApplication.xamlで数百のブラシを定義しています。これらは、プロジェクト内の複数のユーザーコントロールの共有リソースです。それらはすべてパターン化されたキーを持っています:ch_YSD、ch_HJU、ch_IYO ...バインディングに基づいてXAMLでブラシを選択する方法

私はこれらのブラシをデータテンプレートで使用しようとしています。データテンプレートでは、私はYSD、HJU、IYOなどを文字列として取得できるデータテンプレートにある、ブラシキーの可変部分にアクセスできます。

xamlから特定のブラシリソースにどのようにバインドできますか?

現在、私はそのような解決策を持っています:データトリガーを使用して、バインドされた文字列(キーの可変部分)に応じて指定されたブラシに必要なプロパティを設定します。 Application.xaml内のブラシのリストが頻繁に増加するため、私はこの解決策に満足していません。

Application.xamlで共有リソースのメリットを節約するためにメモリを使用したいと思っているのかどうかは分かりません。

答えて

2

シンプルに見えますが、実際には完璧な解決策はありません(または私はそれを見つけられませんでした)。最初のアプローチは、値コンバータを使用することです。しかし、それは動作しません!コンバータで正しく実行できないリソース参照を設定する必要があります。だから、私は正しい方法が付随する行動だと思う。しかし、制限について知っておくべきです。リソースを適用するプロパティは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> 
+0

この優秀な例のおかげで、あなたは私の一日を保存しました! :) – Dima

関連する問題