如何在WPF按钮上移除默认的鼠标悬停效果?

94

我的问题是在WPF中,无论我使用触发器或动画来更改按钮背景的颜色,都会出现默认的鼠标悬停效果(变成灰色并带有橙色光晕),似乎该效果具有优先级。

经过广泛搜索后,我不知道如何去除这种效果。

8个回答

119

这与Mark Heath提到的解决方案类似,但不需要太多代码,只需创建一个非常基本的按钮,而没有内置的鼠标悬停动画效果。它保留了一个简单的鼠标悬停效果,显示黑色的按钮边框。

可以将样式插入Window.Resources或UserControl.Resources部分,例如(如所示)。

<UserControl.Resources>
    <!-- This style is used for buttons, to remove the WPF default 'animated' mouse over effect -->
    <Style x:Key="MyButtonStyle" TargetType="Button">
        <Setter Property="OverridesDefaultStyle" Value="True"/>
        <Setter Property="Margin" Value="5"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="Button">
                    <Border Name="border" 
                        BorderThickness="1"
                        Padding="4,2" 
                        BorderBrush="DarkGray" 
                        CornerRadius="3" 
                        Background="{TemplateBinding Background}">
                        <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
                    </Border>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsMouseOver" Value="True">
                            <Setter TargetName="border" Property="BorderBrush" Value="Black" />
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</UserControl.Resources>

<!-- usage in xaml -->
<Button Style="{StaticResource MyButtonStyle}">Hello!</Button>

2
我非常喜欢那个解决方案。然而,鼠标悬停触发器仅在鼠标悬停在按钮上的文本时才会激活。我在按钮内添加了一个指定宽度的文本块来解决这个问题。 - Dave
3
您真是个圣人。 - krobelusmeetsyndra

36

我想再补充一个非常简单的解决方案,对我来说已经足够好了,并且我认为可以解决问题。我使用了这个答案中的解决方案(链接),只是用普通的Background值代替了图像。

<Style x:Key="SomeButtonStyle" TargetType="Button">
    <Setter Property="Background" Value="Transparent" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="Button">
                <Grid Background="{TemplateBinding Background}">
                    <ContentPresenter />
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

不要重新模板化除了强制使带有模板的按钮的背景始终是透明的背景之外,不应再对其进行更改 - 一旦完成此操作,悬停就不再影响背景。显然,将Transparent替换为任何首选值。


18

您需要创建自己的自定义按钮模板,以完全控制所有状态下的外观。这里是一个教程


2
谢谢,那太完美了。比我想象的要复杂,但现在一切都运行良好。 - Nellius
30
由于某些原因,有大约100个关于创建WPF控件自定义模板的答案,但它们都不必要地错误。没有必要为了更改一个东西而费力地编写50行模板代码来制作一个按钮。你所需要做的就是在XAML设计器中右键单击控件并创建模板代码的副本。 Visual Studio将从该确切按钮创建一个样式,然后您可以从那里进行微调。这只需要几秒钟的时间。 - The Muffin Man
@TheMuffinMan 太棒了,但你是否觉得有点奇怪,需要50行模板代码才能阻止按钮在鼠标悬停时更改背景颜色?WPF是一个非常复杂的框架。 - Ash
@Ash 或者可以说它是引导用户朝着他们应该走的方向前进。如果您有一个需要新悬停状态的按钮,那很可能是一种新类型的按钮;也许是导航按钮、托盘按钮等等。如果是这样,您不应该为其修改一次性属性,而应该拥有自己的控件或样式组。这就是这个功能让您做的事情。 - Matt Kenefick
@TheMuffinMan:你真的是那个人!我已经使用WPF工作了10年,才发现“编辑模板”选项! - Paul
太好了,我不必自己去 C:\Program Files (x86)\Windows Kits\10\DesignTime\CommonConfiguration\Neutral\UAP\10.0.18362.0\Generic\generic.xaml 获取这些模板了。 最好的提示! - Slion

13

麦芬人给了我非常简单的答案。

对于VS 2013,以下提供更加具体的指引:

  • 右键点击控件
  • 选择 编辑模板 => 复制一个...
  • 我选择在'应用程序'中保存样式
    • 从这里您可以直接编辑App.xaml并查看直观命名的属性。 对于我的目的,我只需将RenderMouseOver ="False"设置即可
  • 然后,在MainWindow.xaml或您的GUI所在的任何位置,您可以在Button标记末尾粘贴新样式,例如... Style="{DynamicResource MouseOverNonDefault}"/>

谁是松饼人? - user115014
他在问题所有者接受答案后作出了第二个回复。不确定你是认真提问还是开玩笑。像松饼人这样的名字很难分辨。 - Benji-Man

11

这个链接对我帮助很大 http://www.codescratcher.com/wpf/remove-default-mouse-over-effect-on-wpf-buttons/

UserControl.ResourcesWindow.Resources 中定义一个样式

 <Window.Resources>
        <Style x:Key="MyButton" TargetType="Button">
            <Setter Property="OverridesDefaultStyle" Value="True" />
            <Setter Property="Cursor" Value="Hand" />
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="Button">
                        <Border Name="border" BorderThickness="0" BorderBrush="Black" Background="{TemplateBinding Background}">
                            <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
                        </Border>
                        <ControlTemplate.Triggers>
                            <Trigger Property="IsMouseOver" Value="True">
                                <Setter Property="Opacity" Value="0.8" />
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </Window.Resources>

然后以这种方式向您的按钮添加样式 Style="{StaticResource MyButton}"

<Button Name="btnSecond" Width="350" Height="120" Margin="15" Style="{StaticResource MyButton}">
    <Button.Background>
        <ImageBrush ImageSource="/Remove_Default_Button_Effect;component/Images/WithStyle.jpg"></ImageBrush>
    </Button.Background>
</Button>

4
如果有人不想覆盖默认的控件模板,那么这里有一个解决方案。您可以为按钮创建数据模板,该模板可以具有文本块,然后您可以在IsMouseOver属性上编写属性触发器以禁用鼠标悬停效果。文本块和按钮的高度应该相同。
<Button Background="Black" Margin="0" Padding="0" BorderThickness="0" Cursor="Hand" Height="20">
    <Button.ContentTemplate>
        <DataTemplate>
            <TextBlock Text="GO" Foreground="White" HorizontalAlignment="Center" VerticalAlignment="Center" TextDecorations="Underline" Margin="0" Padding="0" Height="20">
                <TextBlock.Style>
                    <Style TargetType="TextBlock">
                        <Style.Triggers>
                            <Trigger Property ="IsMouseOver" Value="True">
                                <Setter Property= "Background" Value="Black"/>
                            </Trigger>
                        </Style.Triggers>
                    </Style>
                </TextBlock.Style>
            </TextBlock>
        </DataTemplate>
    </Button.ContentTemplate>
</Button>

1
使用模板触发器:
<Style x:Key="ButtonStyle" TargetType="{x:Type Button}">
    <Setter Property="Background" Value="White"></Setter>
    ...
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type Button}">
                <Border Background="{TemplateBinding Background}">
                    <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
                </Border>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsMouseOver" Value="True">
                        <Setter Property="Background" Value="White"/>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

1
扩展dodgy_coder的答案,增加对...的支持。
  • Maintaining WPF button style
  • Adds support for IsSelected and hover, i.e. a toggled button

        <Style x:Key="Button.Hoverless" TargetType="{x:Type ButtonBase}">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type ButtonBase}">
                        <Border Name="border"
                                BorderThickness="{TemplateBinding BorderThickness}"
                                Padding="{TemplateBinding Padding}"
                                BorderBrush="{TemplateBinding BorderBrush}"
                                Background="{TemplateBinding Background}">
                            <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
                        </Border>
                        <ControlTemplate.Triggers>
                            <MultiTrigger>
                                <MultiTrigger.Conditions>
                                    <Condition Property="IsMouseOver" Value="True" />
                                    <Condition Property="Selector.IsSelected" Value="False" />
                                </MultiTrigger.Conditions>
                                <Setter Property="Background" Value="#FFBEE6FD" />
                            </MultiTrigger>
    
                            <MultiTrigger>
                                <MultiTrigger.Conditions>
                                    <Condition Property="IsMouseOver" Value="True" />
                                    <Condition Property="Selector.IsSelected" Value="True" />
                                </MultiTrigger.Conditions>
                                <Setter Property="Background" Value="#BB90EE90" />
                            </MultiTrigger>
    
                            <MultiTrigger>
                                <MultiTrigger.Conditions>
                                    <Condition Property="IsMouseOver" Value="False" />
                                    <Condition Property="Selector.IsSelected" Value="True" />
                                </MultiTrigger.Conditions>
                                <Setter Property="Background" Value="LightGreen" />
                            </MultiTrigger>
    
                            <Trigger Property="IsPressed" Value="True">
                                <Setter TargetName="border" Property="Opacity" Value="0.95" />
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    

示例..

<按钮 内容="擦拭开" Selector.IsSelected="True" /> <按钮 内容="擦拭关" Selector.IsSelected="False" />


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接