我试图遵循XAML的“不要重复自己”的原则,但我已经达到了我正在努力的地步。
我正在为蒙皮定义颜色。 假设我已经定义了我想要基于皮肤的颜色:
<ResourceDictionary>
...
<Color x:Key="B+">#FF999999</Color>
<Color x:Key="B">#FF808080</Color>
<Color x:Key="B-">#FF666666</Color>
...
</ResourceDictionary>
现在说我想使用颜色B作为我的边框颜色,我会设置文本框,按钮等的BorderBrush样式:
<Style TargetType="TextBox">
<Setter Property="BorderBrush">
<Setter.Value>
<SolidColorBrush Color="{StaticResource B}" />
</Setter.Value>
</Setter>
</Style>
<Style TargetType="Button">
<Setter Property="BorderBrush">
<Setter.Value>
<SolidColorBrush Color="{StaticResource B}" />
</Setter.Value>
</Setter>
</Style>
现在假设我想使用更暗的音调,B-,而不是(记住)更改所有控件的资源,我宁愿有一个替代名为“占位符”的颜色来自B,所以我只需要改变一次:
<Color x:Key="controlBorderColor">B</Color><!-- Not working -->
我对如何做到这一点感到茫然。在XAML中是否有一般的“模式”或定义“常量”的方法?
不可能以我想要的方式,看到答案。
简而言之解决方法(感谢@dotsven处理亮度的巧妙技巧):将所有颜色定义为画笔,并使用标记扩展来检索Color
属性。
AFAIK Color
不支持内容分配,因此XAML没有简单的方法来定义或绑定它,而无需单独对A,R,G,B等属性进行分类。画笔类型在这里用作包装器,因此我们可以绑定到Color。
将所有颜色定义为Brush
es
<SolidColorBrush x:Key="B">
<SolidColorBrush.Color>
#FF808080
</SolidColorBrush.Color>
</SolidColorBrush>
创建MarkupExtension以从Color
:
SolidColorBrush
[MarkupExtensionReturnType(typeof(Color))]
public class SkinColorExtension : MarkupExtension {
public SkinColorExtension() {
}
public SkinColorExtension(SolidColorBrush baseColor, int brightness) {
this.BaseColor = baseColor;
this.Brightness = brightness;
}
[ConstructorArgument("baseColor")]
public SolidColorBrush BaseColor { get; set; }
[ConstructorArgument("brightness")]
public int Brightness { get; set; }
public override object ProvideValue(IServiceProvider serviceProvider) {
return SkinColor_Helper.ApplyBrightness(BaseColor.Color, Brightness);
}
}
static class SkinColor_Helper {
public static Color ApplyBrightness(Color c, int b) {
Func<int, byte> Scale = (val) => {
int scaledVal = val + b;
if (scaledVal < 0) return 0;
else if (scaledVal > 255) return 255;
else return (byte)scaledVal;
};
return Color.FromArgb(c.A, Scale(c.R), Scale(c.G), Scale(c.B));
}
}
然后按照亮度偏移创建我的蒙皮颜色:
<SolidColorBrush x:Key="controlBorder" Color="{ext:SkinColor BaseColor={StaticResource B}, Brightness=-25}"/>
<SolidColorBrush x:Key="controlBackground" Color="{ext:SkinColor BaseColor={StaticResource B}, Brightness=-100}" />
当控件需要画笔时,例如Background
,只需绑定到{StaticResource controlBackground}
。
如果必须绑定到需要Color
的内容,请绑定到{ext:SkinColor BaseColor={StaticResource controlBackground}}
以从刷子中检索它。
答案 0 :(得分:2)
不幸的是,无法创建一个属于另一个的别名的静态资源。至少不在XAML中。
如果您可以从代码访问资源字典,那么您可以使用其Add
方法。毕竟它是一本字典。
对于某些类型,例如Style
,您可以使用继承伪造别名。例如:
<Style x:Key="Foo">...</Style>
<Style x:Key="Bar" BasedOn="{StaticResource Foo}"/>
<!-- now Bar is an "alias" for Foo -->
答案 1 :(得分:2)
不幸的是,没有直接的支持。但是通过使用自定义标记扩展,您可以获得灵活的解决方法。创建一个这样的标记扩展:
[MarkupExtensionReturnType(typeof(Color))]
public class RelativeColorExtension : MarkupExtension
{
public RelativeColorExtension()
{
}
public RelativeColorExtension(Color baseColor)
{
this.BaseColor = baseColor;
}
[ConstructorArgument("baseColor")]
public Color BaseColor { get; set; }
public override object ProvideValue(IServiceProvider serviceProvider)
{
return Color.FromArgb(this.BaseColor.A, (Byte)(this.BaseColor.R / 2), (Byte)(this.BaseColor.G /2), (Byte)(this.BaseColor.B / 2));
}
}
然后您可以按如下方式使用它:
<Grid.Resources>
<Color x:Key="Color1" R="10" G="10" B="128" A="255" />
<SolidColorBrush x:Key="Color1Brush" Color="{StaticResource Color1}" />
<SolidColorBrush x:Key="Color2Brush" Color="{ext:RelativeColor BaseColor={StaticResource Color1}}" />
</Grid.Resources>
请注意,您必须在单独的程序集中实现标记扩展。您可以使用允许您以多种方式调暗,变亮或操纵基色的属性来扩展markuop扩展。