web-dev-qa-db-ja.com

スキニング:別の色のStaticResourceとして色を使用する

アプリケーションにスキニングを実装しました。アプリケーションは、スキン固有のリソースディクショナリにある色を使用するBrushes.xamlリソースディクショナリをロードします。そのため、選択したスキンに応じて1つのColor.xamlのみがロードされます。

スキン固有のColor.xaml

    <Color x:Key="TextBoxBackgroundColor">#C4AF8D</Color>
    <Color x:Key="TextBoxForegroundColor">#6B4E2C</Color>
    <Color x:Key="ToolBarButtonForegroundColor">#6B4E2C</Color>

Brushes.xaml:

    <SolidColorBrush 
        x:Key="TextBoxBackground" 
        Color="{DynamicResource TextBoxBackgroundColor}" />
    <SolidColorBrush 
        x:Key="TextBoxForeground" 
        Color="{DynamicResource TextBoxForegroundColor}" />

ご覧のとおり、複数の色(TextBoxForegroundColorとToolBarButtonForegroundColor)は同じです。特に使用される色が16進値で認識できないため、ますます混乱しているので、これを回避したいと思います。両方の色を1つにマージすることをお勧めしますが、TextBoxForegroundColorがToolBarButtonForegroundColorと異なるスキンがあります。

私がやりたいのは次のようなものです:

<Color x:Key="DarkBrown">#C4AF8D</Color>

<Color x:Key="TextBoxBackgroundColor" Color={StaticResource DarkBrown} />
<Color x:Key="ToolBarButtonForegroundColor" Color={StaticResource DarkBrown} />

これはXamlではまったく可能ですか?方法が見つかりませんでした。

43
Amenti

この?

<Color x:Key="DarkBrown">#C4AF8D</Color>

<DynamicResource x:Key="TextBoxBackgroundColor" ResourceKey="DarkBrown"/>
<DynamicResource x:Key="ToolBarButtonForegroundColor" ResourceKey="DarkBrown"/>

より高度な使用例と複数レベルのエイリアシングについては、 this answer を参照してください。

43
H.B.

Brushes.xamlをスキン固有にするだけではどうですか?次に、これがあります:

<Color x:Key="DarkBrown">#C4AF8D</Color>

<SolidColorBrush x:Key="TextBoxBackgroundBrush" Color={StaticResource DarkBrown} />
<SolidColorBrush x:Key="ToolBarButtonForegroundBrush" Color={StaticResource DarkBrown} />

スキン固有のブラシを作成することのもう1つのポイントは、ToolBarButtonForegroundBrushをあるスキンでは無地のブラシに、別のスキンではグラデーションブラシにしたいという状況があることです。

9
Pavlo Glazkov

H.B.の答えは非常に興味深いものであり、この質問が何を求めているのかを正確にしたいので、私はかなりそれをいじっていました。

私が気づいたのは、WPF 3.5ではDynamicResourceの使用が機能しないことです。つまり、実行時に例外がスローされます(Amentiが語っています)。ただし、共有する色を参照している色を作成する場合、StaticResourceは、WPF 3.5とWPF 4.0の両方で機能します。

つまり、このxamlはWPF 3.5とWPF 4.0の両方で機能します。

<Window
    xmlns="http://schemas.Microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.Microsoft.com/winfx/2006/xaml"
    x:Class="ColorsReferencingColors.MainWindow"
    x:Name="Window"
    Title="MainWindow"
    Width="640"
    Height="480"
>
    <Window.Resources>
        <Color x:Key="DarkBlue">DarkBlue</Color>
        <StaticResource x:Key="EllipseBackgroundColor" ResourceKey="DarkBlue"/>
        <SolidColorBrush
            x:Key="ellipseFillBrush"
            Color="{DynamicResource EllipseBackgroundColor}"
        />
    </Window.Resources>
    <Grid>
        <StackPanel Margin="25">
            <Ellipse
                Width="200"
                Height="200"
                Fill="{DynamicResource ellipseFillBrush}"
            />
        </StackPanel>
    </Grid>
</Window>

もう1つ言及しなければならないことは、このアプローチは、そこにいるデザイナー(つまり、Visual Studio 2008および2010デザイナー、Blend 3および4デザイナー)に大混乱をもたらすことです。これは、Kaxaml 1.7がH.B.のxamlを好まなかったのと同じ理由であると推測します(H.B.の回答のコメントストリームをフォローしている場合)。

しかし、単純なテストケースでは設計者を破壊しますが、私が日々の仕事で取り組んでいる大規模なアプリケーションの設計面を破壊するようには見えません。普通じゃない!つまり、デザイナーでまだ機能していることに関心がある場合は、とにかくこの方法を試してみてください。

7
cplotts

ColorにはColorプロパティがないため、その最後の部分は不可能です。

A Colorには、R、G、B、およびAプロパティがあります。したがって、リソースとして4バイトを作成できます。

<ResourceDictionary xmlns="http://schemas.Microsoft.com/winfx/2006/xaml/presentation"
     xmlns:x="http://schemas.Microsoft.com/winfx/2006/xaml"
     xmlns:sys="clr-namespace:System;Assembly=mscorlib">
    <sys:Byte x:Key="r">#23</sys:Byte>
    <sys:Byte x:Key="g">#45</sys:Byte>
    <sys:Byte x:Key="b">#67</sys:Byte>
    <sys:Byte x:Key="a">#FF</sys:Byte>

    <Color x:Key="c1" R="{StaticResource r}"
       G="{StaticResource g}"
       B="{StaticResource b}"
       A="{StaticResource a}"/>

    <Color x:Key="c2" R="{StaticResource r}"
       G="{StaticResource g}"
       B="{StaticResource b}"
       A="{StaticResource a}"/>

</ResourceDictionary>

それでもあなたが好むかもしれないものではありませんが、それは動作するはずです。

3
Erno de Weerd