问题域:在我的 WPF 应用程序中,我根据它们包含的数据动态更改了许多 UI 控件(如 Button 或 ListItems)的背景。加载控件时或根据接收到的使用操作/数据更改背景。
问题陈述:如果背景太暗(绿色/蓝色),我想将前景设置为白色,否则为黑色。
约束:我有一个很大的应用程序,性能是一个主要问题。这就是为什么我对使用转换器犹豫不决,并且正在寻找一些基于 xaml/style 触发器的解决方案,因为这只是一个基于条件的问题。
尝试的解决方案:为了简单起见,我正在解释我为一个简单的 wpf 按钮尝试的内容:
<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}"/>
另外,我想指出上述风格的几件事:
- 如果我在名为 Chrome 的网格中使用 ContentPresenter 而不是 TextBlock,则不会在 ContentPresenter 上设置背景属性,当我窥探(http://snoopwpf.codeplex.com/)UI时,我发现 ContentPresenter 具有 TextBlock,其背景始终设置为默认值,因此没有将样式触发器应用于 TextBlock。此外,此 TextBlock 的背景值源是默认值。
另一方面,当我直接在名为 Chrome 的网格中使用 TextBlock 时,我可以将其背景显式设置为设置为按钮背景的网格背景。Snooping 显示现在 TextBlock 的 Background ValueSource 是 ParentTemplate。
Button 在显示其内容时选择 MyTextBlockStyle。
永远不会触发 Button 或 TextBlock 的样式触发器,除非我将鼠标悬停在将按钮的背景更改为黑色并将此值向下传播到 TextBlock 背景的按钮上,从而将 TextBlock 的前景色更改为 DarkSeaGreen。
此外,在应用程序运行时更改 snoop 实用程序中按钮的背景会触发样式触发器。
问题:
为什么没有一个 Style 触发器适用于 Background 属性,而它们适用于 IsMouseOver 属性?
我做错了什么?
有什么解决办法吗?