【问题标题】:WPF hover border effect not being applied未应用 WPF 悬停边框效果
【发布时间】:2020-11-16 19:04:23
【问题描述】:

当鼠标悬停在 WPF 中的控件上时,我正在尝试(但失败)更改单选按钮上圆圈边框的颜色。我的Style WPF 如下:

<Style TargetType="RadioButton"
        x:Key="RadioButtonStyling"
        BasedOn="{StaticResource {x:Type RadioButton}}">
    <Style.Triggers>
        <Trigger Property="IsMouseOver" Value="True">
            <Setter Property="BorderBrush" Value="Red" />
        </Trigger>
    </Style.Triggers>
</Style

然后我在单选按钮上调用它,如下所示:

<RadioButton Style="{StaticResource RadioButtonStyling}" ... />

就目前而言,圆形的轮廓没有应用任何样式,它仍然是默认的蓝色(开箱即用的 Windows 式蓝色)。见下图

【问题讨论】:

  • 单选按钮并不是那么简单。您必须先覆盖单选按钮的控件模板,然后才能更改单选按钮控件部分的边框颜色,即那个小圆圈。
  • 如果你在 VS2019 中,这几天相当简单。只需右键单击单选按钮并选择“编辑样式”。这将创建一种扩展单选按钮内部工作的样式,以便您可以仅更改 Ellipse 上的边框颜色,该 Ellipse 是指示它被选中的控件的一部分。

标签: wpf xaml user-interface


【解决方案1】:

问题是单选按钮的模板中已经有一个鼠标悬停触发器。

这会按名称设置边框元素上的边框笔刷,因此将覆盖您的触发器设置控件边框的值。

这是 win 10 模板的修改工作版本,它在鼠标悬停时将圆圈设置为红色:

    <ControlTemplate x:Key="RadioButtonControlTemplate1" TargetType="{x:Type RadioButton}">
        <Grid x:Name="templateRoot" Background="Transparent" SnapsToDevicePixels="True">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto"/>
                <ColumnDefinition Width="*"/>
            </Grid.ColumnDefinitions>
            <Border x:Name="radioButtonBorder" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" CornerRadius="100" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="1,1,2,1" VerticalAlignment="{TemplateBinding VerticalContentAlignment}">
                <Grid x:Name="markGrid" Margin="2">
                    <Ellipse x:Name="optionMark" Fill="#FF212121" MinWidth="6" MinHeight="6" Opacity="0"/>
                </Grid>
            </Border>
            <ContentPresenter x:Name="contentPresenter" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" Grid.Column="1" ContentStringFormat="{TemplateBinding ContentStringFormat}" Focusable="False" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
        </Grid>
        <ControlTemplate.Triggers>
            <Trigger Property="HasContent" Value="True">
                <Setter Property="FocusVisualStyle">
                    <Setter.Value>
                        <Style>
                            <Setter Property="Control.Template">
                                <Setter.Value>
                                    <ControlTemplate>
                                        <Rectangle Margin="14,0,0,0" SnapsToDevicePixels="True" Stroke="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" StrokeThickness="1" StrokeDashArray="1 2"/>
                                    </ControlTemplate>
                                </Setter.Value>
                            </Setter>
                        </Style>
                    </Setter.Value>
                </Setter>
                <Setter Property="Padding" Value="4,-1,0,0"/>
            </Trigger>
            <Trigger Property="IsEnabled" Value="False">
                <Setter Property="Background" TargetName="radioButtonBorder" Value="#FFE6E6E6"/>
                <Setter Property="BorderBrush" TargetName="radioButtonBorder" Value="#FFBCBCBC"/>
                <Setter Property="Fill" TargetName="optionMark" Value="#FF707070"/>
            </Trigger>
            <Trigger Property="IsMouseOver" Value="True">
                <Setter Property="Background" TargetName="radioButtonBorder" Value="#FFF3F9FF"/>
                <Setter Property="BorderBrush" TargetName="radioButtonBorder" Value="Red"/>
                <Setter Property="Fill" TargetName="optionMark" Value="#FF212121"/>
            </Trigger>
            <Trigger Property="IsPressed" Value="True">
                <Setter Property="Background" TargetName="radioButtonBorder" Value="#FFD9ECFF"/>
                <Setter Property="BorderBrush" TargetName="radioButtonBorder" Value="#FF3C77DD"/>
                <Setter Property="Fill" TargetName="optionMark" Value="#FF212121"/>
            </Trigger>
            <Trigger Property="IsChecked" Value="True">
                <Setter Property="Opacity" TargetName="optionMark" Value="1"/>
            </Trigger>
            <Trigger Property="IsChecked" Value="{x:Null}">
                <Setter Property="Opacity" TargetName="optionMark" Value="0.56"/>
            </Trigger>
        </ControlTemplate.Triggers>
    </ControlTemplate>

关键部分是这个触发器:

        <Trigger Property="IsMouseOver" Value="True">
            <Setter Property="Background" TargetName="radioButtonBorder" Value="#FFF3F9FF"/>
            <Setter Property="BorderBrush" TargetName="radioButtonBorder" Value="Red"/>
            <Setter Property="Fill" TargetName="optionMark" Value="#FF212121"/>
        </Trigger>

我已将原始值更改为“红色”

我还按触发器的顺序将该触发器向下移动,因此它在启用之后。

这些是我对提取的默认 win10 模板所做的唯一更改。

【讨论】:

    【解决方案2】:

    WPF 中的每个控件都有不同的状态,例如 inactivemouse-overpresseddisabled。如果您想修改某些状态,样式上的简单设置器将不起作用,因为控件模板中已经定义了触发器,这些触发器将覆盖您的触发器。

    因此,您需要创建自定义控件模板。您可以使用 Visual Studio 或 Blend 等工具来自动提取您可以编辑的默认控件模板。提取后,您将获得一种或多种样式以及如下所示的画笔列表。

    <SolidColorBrush x:Key="RadioButton.Static.Background" Color="#FFFFFFFF"/>
    <SolidColorBrush x:Key="RadioButton.Static.Border" Color="#FF707070"/>
    <SolidColorBrush x:Key="RadioButton.Static.Glyph" Color="#FF212121"/>
    <SolidColorBrush x:Key="RadioButton.MouseOver.Background" Color="#FFF3F9FF"/>
    <SolidColorBrush x:Key="RadioButton.MouseOver.Border" Color="#FF5593FF"/>
    <SolidColorBrush x:Key="RadioButton.MouseOver.Glyph" Color="#FF212121"/>
    <!-- ...and so on. -->
    
    <Style x:Key="OptionMarkFocusVisual">
       <!-- ...style used for displaying focus. -->
    </Style>
    <Style x:Key="RadioButtonStyle" TargetType="{x:Type RadioButton}">
       <Setter Property="FocusVisualStyle" Value="{StaticResource FocusVisual}"/>
       <Setter Property="Background" Value="{StaticResource RadioButton.Static.Background}"/>
       <Setter Property="BorderBrush" Value="{StaticResource RadioButton.Static.Border}"/>
       <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
       <Setter Property="BorderThickness" Value="1"/>
       <Setter Property="Template">
          <Setter.Value>
             <ControlTemplate TargetType="{x:Type RadioButton}">
                <!-- ...control template to display the radio button -->
             </ControlTemplate>
          </Setter.Value>
       </Setter>
    </Style>
    

    在您的情况下,您只需覆盖 mouse-over 状态的边框画笔。

    <SolidColorBrush x:Key="RadioButton.MouseOver.Border" Color="Red"/>
    

    然后将更改后的样式应用到单选按钮。

    <RadioButton Style="{DynamicResource RadioButtonStyle}"/>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-02-24
      • 2015-04-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-09-10
      • 2016-03-17
      • 2021-08-29
      相关资源
      最近更新 更多