【问题标题】:Can't change background button property anymore if mouseOver have been overridden如果 mouseOver 已被覆盖,则无法再更改背景按钮属性
【发布时间】:2020-12-13 12:27:53
【问题描述】:

在下图中,我有 3 个按钮 (UserControls),我更改了默认的 mouseOver 效果。在图片中,我当前将鼠标悬停在按钮 1 上。

这是我使用的代码:

<Style x:Key="ButtonMouseOver" TargetType="{x:Type Button}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type Button}">
                <Border>
                    <Border.Style>
                        <Style TargetType="{x:Type Border}">
                             <Style.Triggers>
                                <Trigger Property="IsMouseOver" Value="True">
                                    <Setter Property="Background" Value="#404040"/>
                                </Trigger>
                            </Style.Triggers>
                        </Style>
                    </Border.Style>
                    <Grid Background="Transparent">
                        <ContentPresenter></ContentPresenter>
                    </Grid>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

我的用户控制按钮:

<Button HorizontalContentAlignment="Stretch" Style="{StaticResource ButtonMouseOver}" VerticalContentAlignment="Stretch" Background="{Binding ButtonColor}" BorderThickness="0">

但现在,我无法再使用Background 属性更改按钮的颜色。任何想法为什么?

【问题讨论】:

    标签: c# wpf xaml mouseover controltemplate


    【解决方案1】:

    当您覆盖 ControlTemplate 时,您必须小心使用 TemplateBinding 绑定到模板化目标控件的属性,否则它们会采用默认值或您在模板中分配的显式值,但它们不能直接覆盖,也不能在 Style 中覆盖。

    在您的示例中,您必须将BorderBackgroundTemplateBinding 绑定,以便它使用来自模板化ButtonBackground 属性的值。您应该对Button 的所有属性执行此操作以启用不同的样式。

    <ControlTemplate TargetType="{x:Type Button}">
       <Border Background="{TemplateBinding Background}">
       <!-- ...other definitions -->
    </ControlTemplate>
    

    来自TemplateBindingdocumentation

    将控件模板中的属性值链接为模板化控件上另一个属性的值。

    这是您的控件模板的简化版本,其中包含用于背景的模板绑定,以及在其样式中定义的默认值,可以在其他样式中或直接在按钮上覆盖。

    <Style x:Key="ButtonMouseOver" TargetType="{x:Type Button}">
       <Setter Property="Background"
               Value="#777777"/>
       <Setter Property="Template">
          <Setter.Value>
             <ControlTemplate TargetType="{x:Type Button}">
                <Border x:Name="MyBorder"
                        Background="{TemplateBinding Background}">
                   <ContentPresenter HorizontalAlignment="Center"
                                     VerticalAlignment="Center"/>
                </Border>
                <ControlTemplate.Triggers>
                   <Trigger Property="IsMouseOver"
                            Value="True">
                      <Setter TargetName="MyBorder"
                              Property="Background"
                              Value="#404040"/>
                   </Trigger>
                </ControlTemplate.Triggers>
             </ControlTemplate>
          </Setter.Value>
       </Setter>
    </Style>
    

    【讨论】:

    • 嗯...现在我可以看到颜色变化了,但是按钮单击和 mouseOver 不再起作用了
    • 其实我用TemplateBinding的时候,边框的背景会和我按钮的背景一样吗?
    • @ÉmilePettersen-Coulombe 鼠标悬停不起作用,因为您在 Style 来回边界中定义了它。不要那样做,而是使用ControlTemplate的触发器,然后它就可以工作了。看看这个exampleBorder 是模板中的根控件,因此设置其Background 将为按钮设置背景。
    • 我查看了这个解决方案:stackoverflow.com/questions/20073294/… 我真的不明白为什么或如何使用ControlTemplate 的触发器,但是如果我直接在按钮上放置背景属性,则没有mouseOver 触发。如果我将背景属性放在 setter 标记的 button.style 部分中,则 mouseOver 正在工作。
    • @ÉmilePettersen-Coulombe 在您的链接帖子中,查看已接受答案下方的答案,它使用模板触发器。您应该使用控制模板触发器的原因是它们采用precedence 而不是样式。
    猜你喜欢
    • 2017-04-29
    • 1970-01-01
    • 2011-02-02
    • 2018-02-05
    • 2022-01-16
    • 1970-01-01
    • 2014-11-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多