1

Application.xamlで数百のブラシが定義されています。これらは、プロジェクト内のいくつかのユーザーコントロールの共有リソースです。それらはすべてパターン化されたキーを持っています:ch_YSD、ch_HJU、ch_IYO .. ..

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

xamlから特定のブラシリソースにバインドするにはどうすればよいですか?

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

Application.xamlの共有リソースのメモリ節約の利点を利用したいので、コードビハインドを使用する必要があるかどうかわかりません。

4

1 に答える 1

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>
于 2012-04-08T17:59:18.030 に答える