【问题标题】:WPF Button Style Background hidding ForegroundWPF 按钮样式背景隐藏前景
【发布时间】:2023-08-23 13:56:01
【问题描述】:

我正在尝试了解使用模板设置控件样式的基础知识,但即使有很多示例,我仍然坚持一些基础知识。

我希望使用自定义背景设置按钮的样式,因此我设置了一个边框,其背景属性在 VisualState“MouseOver”上发生了变化。问题是,因为我在边框上设置了颜色,所以我找不到如何将我的文本前景属性设置为白色以便文本可见。

这是我的 xaml:

   <Style TargetType="{x:Type Button}">
        <Setter Property="Foreground" Value="White"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="Button">
                    <Border Name="RootElement">
                        <Border.Background>
                            <LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
                                <GradientStop Offset="0" Color="Black" />
                                <GradientStop Offset="1" Color="SteelBlue" />
                            </LinearGradientBrush>
                        </Border.Background>
                        <VisualStateManager.VisualStateGroups>
                            <VisualStateGroup x:Name="CommonStates">
                                <VisualState x:Name="Normal" />
                                <VisualState x:Name="MouseOver">
                                    <Storyboard>
                                        <ColorAnimationUsingKeyFrames Storyboard.TargetName="RootElement" Storyboard.TargetProperty="(Border.Background).(GradientBrush.GradientStops)[1].(GradientStop.Color)">
                                            <EasingColorKeyFrame KeyTime="0" Value="LightSteelBlue" />
                                        </ColorAnimationUsingKeyFrames>
                                    </Storyboard>
                                </VisualState>
                            </VisualStateGroup>
                        </VisualStateManager.VisualStateGroups>
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

Foreground 属性的设置器似乎被边框背景属性覆盖。

我想我必须在模板中添加一个文本块,但我确定如何将按钮的实际文本链接到 textBlock,这是我尝试但没有成功的方法:

    <Style TargetType="{x:Type Button}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="Button">
                    <Border Name="RootElement">
                        <Border.Background>
                            <LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
                                <GradientStop Offset="0" Color="Black" />
                                <GradientStop Offset="1" Color="SteelBlue" />
                            </LinearGradientBrush>
                        </Border.Background>
                        <VisualStateManager.VisualStateGroups>
                            <VisualStateGroup x:Name="CommonStates">
                                <VisualState x:Name="Normal" />
                                <VisualState x:Name="MouseOver">
                                    <Storyboard>
                                        <ColorAnimationUsingKeyFrames Storyboard.TargetName="RootElement" Storyboard.TargetProperty="(Border.Background).(GradientBrush.GradientStops)[1].(GradientStop.Color)">
                                            <EasingColorKeyFrame KeyTime="0" Value="LightSteelBlue" />
                                        </ColorAnimationUsingKeyFrames>
                                    </Storyboard>
                                </VisualState>
                            </VisualStateGroup>
                        </VisualStateManager.VisualStateGroups>
                        <TextBlock Name="ButtonText" Text="{TemplateBinding Content}">
                            <TextBlock.Foreground>
                                <SolidColorBrush Color="White"/>
                            </TextBlock.Foreground>
                        </TextBlock>
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

【问题讨论】:

  • 我刚刚尝试了您的第二种样式,它看起来对我来说很合适,我在按钮上获得了非常漂亮的黑色到蓝色背景颜色和白色文本。

标签: wpf templates foreground


【解决方案1】:

你是正确的,你需要添加一些东西来呈现 Button 中的文本,边框内的简单 ContentPrsenter 应该可以。

   <Style TargetType="{x:Type Button}">
            <Setter Property="Foreground" Value="White"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="Button">
                        <Border Name="RootElement">
                            <Border.Background>
                                <LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
                                    <GradientStop Offset="0" Color="Black" />
                                    <GradientStop Offset="1" Color="SteelBlue" />
                                </LinearGradientBrush>
                            </Border.Background>
                            <VisualStateManager.VisualStateGroups>
                                <VisualStateGroup x:Name="CommonStates">
                                    <VisualState x:Name="Normal" />
                                    <VisualState x:Name="MouseOver">
                                        <Storyboard>
                                            <ColorAnimationUsingKeyFrames Storyboard.TargetName="RootElement" Storyboard.TargetProperty="(Border.Background).(GradientBrush.GradientStops)[1].(GradientStop.Color)">
                                                <EasingColorKeyFrame KeyTime="0" Value="LightSteelBlue" />
                                            </ColorAnimationUsingKeyFrames>
                                        </Storyboard>
                                    </VisualState>
                                </VisualStateGroup>
                            </VisualStateManager.VisualStateGroups>

                            <ContentPresenter/>

                        </Border>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

如果您想更好地控制显示内容的内容,您可以添加标签之类的内容并绑定到按钮的 Content 属性。

  <Style TargetType="{x:Type Button}">
        <Setter Property="Foreground" Value="White"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="Button">
                    <Border Name="RootElement">
                        <Border.Background>
                            <LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
                                <GradientStop Offset="0" Color="Black" />
                                <GradientStop Offset="1" Color="SteelBlue" />
                            </LinearGradientBrush>
                        </Border.Background>
                        <VisualStateManager.VisualStateGroups>
                            <VisualStateGroup x:Name="CommonStates">
                                <VisualState x:Name="Normal" />
                                <VisualState x:Name="MouseOver">
                                    <Storyboard>
                                        <ColorAnimationUsingKeyFrames Storyboard.TargetName="RootElement" Storyboard.TargetProperty="(Border.Background).(GradientBrush.GradientStops)[1].(GradientStop.Color)">
                                            <EasingColorKeyFrame KeyTime="0" Value="LightSteelBlue" />
                                        </ColorAnimationUsingKeyFrames>
                                    </Storyboard>
                                </VisualState>
                            </VisualStateGroup>
                        </VisualStateManager.VisualStateGroups>

                        <Label Content="{TemplateBinding Content}" Foreground="{TemplateBinding Foreground}"/>
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

【讨论】:

  • 非常感谢您的快速回复,这解决了我的问题。怎么可能“模板绑定内容”实际上是使用标签而不是文本块?
  • 其实它对 TextBlock 也是如此,只要其中有一个字符串,我认为按钮 Content 属性的 Type 是 Object。
  • 我知道晚了,但为什么是边框背景而不是按钮背景?