Скиннинг: использование цвета в качестве статического ресурса для другого цвета

Я реализовал скиннинг в своем приложении. Приложение загружает свой словарь ресурсов Brushes.xaml, в котором используются цвета, находящиеся в словаре ресурсов для определенного скина. Таким образом, загружается только один 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) одинаковы. Я хотел бы обойти это, поскольку это становится все более и более запутанным, тем более что используемые цвета не распознаются по их шестнадцатеричному значению. Теперь вы можете посоветовать объединить оба цвета в один, но у меня есть обложки, в которых TextBoxForegroundColor отличается от ToolBarButtonForegroundColor.

Я хотел бы сделать что-то вроде этого:

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

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

Это вообще возможно в Xaml? Я не нашел способ.

4 ответа

Решение

Это?

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

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

Для более сложных вариантов использования и нескольких уровней псевдонимов см. Этот ответ.

Почему бы вам просто не сделать Brushes.xaml специфичным для кожи? Тогда у вас будет это:

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

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

Еще один момент в пользу создания кистей, специфичных для кожи, состоит в том, что есть ситуации, когда вы хотите сделать ToolBarButtonForegroundBrush однотонная кисть в одной коже и градиентная кисть в другой.

Ответ HB очень интересен, и я немного поиграл с ним, так как хочу сделать именно то, что задает этот вопрос.

Я заметил, что использование DynamicResource не работает для WPF 3.5. То есть он генерирует исключение во время выполнения (тот, о котором говорит Аменти). Однако, если вы создаете цвета, которые ссылаются на цвет, которым вы хотите поделиться... 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>

Еще одна вещь, о которой стоит упомянуть (опять же), это то, что этот подход наносит ущерб дизайнерам (то есть дизайнерам Visual Studio 2008 и 2010, дизайнерам Blend 3 и 4). Я предполагаю, что это та же самая причина, почему Kaxaml 1.7 не понравился xaml HB (если вы следите за потоком комментариев относительно ответа HB).

Но несмотря на то, что это ломает дизайнеров для простого тестового примера, это, похоже, не нарушает дизайн для крупномасштабного приложения, над которым я работаю в своей повседневной работе. Просто странно! Другими словами, если вы заботитесь о вещах, которые все еще работают в конструкторе, попробуйте этот метод в любом случае... ваш дизайнер все еще может работать!

Последняя часть невозможна, так как цвет не имеет свойства цвета.

Цвет имеет свойства R, G, B и A. Таким образом, вы можете создать четыре байта в качестве ресурсов:

<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>

Все еще не то, что вы могли бы предпочесть, но это должно работать.

Другие вопросы по тегам