Wpf 基于背景色动态更改前景色
问题域:在我的WPF应用程序中,我根据按钮或列表项所包含的数据动态更改了许多UI控件的背景。加载控件时或根据收到的使用操作/数据更改背景 问题陈述:如果背景太暗(绿色/蓝色),我想将前景设置为白色或黑色 限制:我有一个大型应用程序,性能是一个主要问题。这就是为什么我对使用转换器犹豫不决,并且正在寻找一些基于xaml/风格触发器的解决方案,因为这只是一个基于条件的问题 尝试的解决方案:为了保持简单,我正在解释我尝试的简单wpf按钮:Wpf 基于背景色动态更改前景色,wpf,button,colors,triggers,styles,Wpf,Button,Colors,Triggers,Styles,问题域:在我的WPF应用程序中,我根据按钮或列表项所包含的数据动态更改了许多UI控件的背景。加载控件时或根据收到的使用操作/数据更改背景 问题陈述:如果背景太暗(绿色/蓝色),我想将前景设置为白色或黑色 限制:我有一个大型应用程序,性能是一个主要问题。这就是为什么我对使用转换器犹豫不决,并且正在寻找一些基于xaml/风格触发器的解决方案,因为这只是一个基于条件的问题 尝试的解决方案:为了保持简单,我正在解释我尝试的简单wpf按钮: <UserControl.Resources> &l
<UserControl.Resources>
<Style x:Key="NoChromeButton" TargetType="{x:Type Button}">
<Setter Property="Background" Value="{Binding Background}"/>
<Setter Property="OverridesDefaultStyle" Value="True"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="BorderBrush" Value="White"/>
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Padding" Value="1"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Grid x:Name="Chrome"
Background="{TemplateBinding Background}"
SnapsToDevicePixels="true"
HorizontalAlignment="Stretch">
<TextBlock
Text="{Binding RelativeSource={RelativeSource TemplatedParent},Path=Content}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
Margin="{TemplateBinding Padding}"
Background="{Binding RelativeSource={RelativeSource TemplatedParent},Path=Background}"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
Style="{StaticResource MyTextBlockStyle}"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="Black"/>
</Trigger>
<Trigger Property="Background" Value="White">
<Setter Property="Foreground" Value="Aqua"/>
</Trigger>
<Trigger Property="Background" Value="Transparent">
<Setter Property="Foreground" Value="BlueViolet"/>
</Trigger>
<Trigger Property="Background" Value="Green">
<Setter Property="Foreground" Value="Blue"/>
</Trigger>
<Trigger Property="Background" Value="Yellow">
<Setter Property="Foreground" Value="Red"/>
</Trigger>
<Trigger Property="Background" Value="Red">
<Setter Property="Foreground" Value="Yellow"/>
</Trigger>
<Trigger Property="Background" Value="Black">
<Setter Property="Foreground" Value="DarkSeaGreen"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style x:key="MyTextBlockStyle" TargetType="TextBlock">
<Setter Property="FontSize" Value="12"/>
<Setter Property="FontStyle" Value="Italic"/>
<Style.Triggers>
<Trigger Property="Background" Value="White">
<Setter Property="Foreground" Value="Aqua"/>
</Trigger>
<Trigger Property="Background" Value="Transparent">
<Setter Property="Foreground" Value="BlueViolet"/>
</Trigger>
<Trigger Property="Background" Value="Green">
<Setter Property="Foreground" Value="Blue"/>
</Trigger>
<Trigger Property="Background" Value="Yellow">
<Setter Property="Foreground" Value="Red"/>
</Trigger>
<Trigger Property="Background" Value="Red">
<Setter Property="Foreground" Value="Yellow"/>
</Trigger>
<Trigger Property="Background" Value="Black">
<Setter Property="Foreground" Value="DarkSeaGreen"/>
</Trigger>
</Style>
</UserControl.Resources>
在XAML中创建按钮时:
<Button Content="{Binding Name}" Style="{StaticResource NoChromeButton}"/>
此外,我想指出上述风格中的几点:
我找到了解决我问题的办法。 TextBlock不是从控件派生的。任何控件在UI上显示的任何文本在内部都使用TextBlock来表示文本内容。如果使用ResourceDictionary中的以下命令设置TextBlock样式:
<Style TargetType="TextBlock">
<Setter Property="FontFamily" Value="Arial" />
<Setter Property="FontSize" Value="12" />
<Setter Property="FontStyle" Value="Normal" />
</Style>
任何表示文本的控件都将具有此样式(因为没有为该样式分配任何键,这意味着默认情况下所有TextBlock都将获得该样式),除非该控件的模板覆盖TextBlock的默认样式,该默认样式可按以下方式完成:
<Button Grid.Column="1" Style="{StaticResource NoChromeButton}">
<TextBlock Style="{x:Null}" Text="abc" FontFamily="Segoe UI Symbol"/>
</Button>
这个简单的设置解决了我们在动态前景色变化方面的大多数问题。由于性能方面的考虑,我们更喜欢触发器而不是转换器,这对我来说似乎是过早的优化。我敢打赌你甚至还没有对它们之间的差异进行基准测试。