蒙皮:使用Color作为另一种颜色的StaticResource

时间:2011-01-26 08:09:04

标签: wpf colors skinning resourcedictionary

我在我的应用程序中实现了皮肤。应用程序加载其Brushes.xaml资源字典,该字典使用驻留在特定于皮肤的资源字典中的颜色。因此,根据所选皮肤,只加载一个Color.xaml。

Skin-Specific 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 个答案:

答案 0 :(得分:43)

此?

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

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

有关更高级的用例和多个别名级别,请参阅this answer

答案 1 :(得分:9)

为什么不让Brushes.xaml特定于皮肤?然后你会有这个:

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

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

支持制作特定于皮肤的画笔的另一点是,在某些情况下,您可能希望在一个皮肤中使用ToolBarButtonForegroundBrush作为纯色画笔,在另一个皮肤中使用渐变画笔。

答案 2 :(得分:7)

H.B.的答案非常有趣,我已经玩了很多,因为我想完全按照这个问题的要求去做。

我注意到使用DynamicResource不适用于WPF 3.5。也就是说,它在运行时抛出一个异常(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>

另一件值得提及的事情是,这种方法会对设计师造成严重破坏(即Visual Studio 2008和2010设计师,Blend 3和4设计师)。我猜测这就是为什么Kaxaml 1.7不喜欢H.B.的xaml(如果你跟随H.B.答案的评论流)。

虽然它打破了设计师的简单测试案例,但它似乎并没有打破我在日常工作中工作的大规模应用程序的设计界面。简直怪异!换句话说,如果你关心设计师仍在使用的东西,无论如何都要尝试这种方法......你的设计师仍然可以工作!

答案 3 :(得分:3)

由于Color没有Color属性,因此无法使用最后一部分。

颜色确实具有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>

仍然不是你想要的,但它应该有用。