You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过纯代码方式禁用WPF Button的鼠标悬停效果?

纯代码实现禁用WPF Button悬停高亮效果

要完全通过代码禁用Button的鼠标/触摸悬停高亮,核心是重写Button的ControlTemplate,移除MouseOver状态的触发动画,再将这个自定义模板封装为全局样式应用。

步骤1:创建自定义ControlTemplate

这个模板保留Button的基础结构,但去掉悬停时的颜色变化:

private static ControlTemplate CreateNoHoverButtonTemplate()
{
    // 构建模板根元素Border
    var borderFactory = new FrameworkElementFactory(typeof(Border));
    borderFactory.SetValue(Border.NameProperty, "buttonBorder");
    // 绑定默认属性,保持Button原有外观基础
    borderFactory.SetValue(Border.BackgroundProperty, new TemplateBindingExtension(Button.BackgroundProperty));
    borderFactory.SetValue(Border.BorderBrushProperty, new TemplateBindingExtension(Button.BorderBrushProperty));
    borderFactory.SetValue(Border.BorderThicknessProperty, new TemplateBindingExtension(Button.BorderThicknessProperty));
    borderFactory.SetValue(Border.CornerRadiusProperty, new CornerRadius(3)); // 匹配默认Button圆角

    // 添加内容展示容器ContentPresenter
    var contentPresenterFactory = new FrameworkElementFactory(typeof(ContentPresenter));
    contentPresenterFactory.SetValue(ContentPresenter.HorizontalAlignmentProperty, HorizontalAlignment.Center);
    contentPresenterFactory.SetValue(ContentPresenter.VerticalAlignmentProperty, VerticalAlignment.Center);
    contentPresenterFactory.SetValue(ContentPresenter.MarginProperty, new Thickness(2));
    contentPresenterFactory.SetValue(ContentPresenter.ContentProperty, new TemplateBindingExtension(Button.ContentProperty));
    contentPresenterFactory.SetValue(ContentPresenter.ContentTemplateProperty, new TemplateBindingExtension(Button.ContentTemplateProperty));

    borderFactory.AppendChild(contentPresenterFactory);

    // 创建ControlTemplate实例
    var template = new ControlTemplate(typeof(Button));
    template.VisualTree = borderFactory;

    // 配置VisualStateManager,移除悬停高亮
    var commonStatesGroup = new VisualStateGroup { Name = "CommonStates" };

    // 正常状态:无动画
    commonStatesGroup.States.Add(new VisualState { Name = "Normal" });

    // 按压状态:可选保留按压效果,不需要可以删除这段
    var pressedState = new VisualState { Name = "Pressed" };
    var pressedStoryboard = new Storyboard();
    var bgAnimation = new ColorAnimationUsingKeyFrames();
    bgAnimation.KeyFrames.Add(new EasingColorKeyFrame(Colors.DarkGray, KeyTime.FromTimeSpan(TimeSpan.Zero)));
    Storyboard.SetTargetName(bgAnimation, "buttonBorder");
    Storyboard.SetTargetProperty(bgAnimation, new PropertyPath("Background.Color"));
    pressedStoryboard.Children.Add(bgAnimation);
    pressedState.Storyboard = pressedStoryboard;
    commonStatesGroup.States.Add(pressedState);

    // 禁用状态:保留灰化效果
    var disabledState = new VisualState { Name = "Disabled" };
    var disabledStoryboard = new Storyboard();
    var disabledBgAnimation = new ColorAnimationUsingKeyFrames();
    disabledBgAnimation.KeyFrames.Add(new EasingColorKeyFrame(Colors.LightGray, KeyTime.FromTimeSpan(TimeSpan.Zero)));
    Storyboard.SetTargetName(disabledBgAnimation, "buttonBorder");
    Storyboard.SetTargetProperty(disabledBgAnimation, new PropertyPath("Background.Color"));
    disabledStoryboard.Children.Add(disabledBgAnimation);
    disabledState.Storyboard = disabledStoryboard;
    commonStatesGroup.States.Add(disabledState);

    // 悬停状态:空动画,无任何变化
    commonStatesGroup.States.Add(new VisualState { Name = "MouseOver" });

    // 将状态组绑定到模板根元素
    VisualStateManager.SetVisualStateGroups(borderFactory, new VisualStateGroupCollection { commonStatesGroup });

    return template;
}

步骤2:创建全局样式并应用

将上面的模板封装为Style,添加到应用全局资源,所有CustomButton会自动生效:

// 在应用启动时执行(比如App.xaml.cs的OnStartup方法)
var customButtonStyle = new Style(typeof(CustomButton));
// 绑定自定义模板
customButtonStyle.Setters.Add(new Setter(Button.TemplateProperty, CreateNoHoverButtonTemplate()));
// 设置默认外观属性,匹配系统默认Button样式
customButtonStyle.Setters.Add(new Setter(Button.BackgroundProperty, SystemColors.ControlBrush));
customButtonStyle.Setters.Add(new Setter(Button.ForegroundProperty, SystemColors.ControlTextBrush));
customButtonStyle.Setters.Add(new Setter(Button.BorderBrushProperty, SystemColors.ControlDarkBrush));
customButtonStyle.Setters.Add(new Setter(Button.BorderThicknessProperty, new Thickness(1)));

// 添加到应用全局资源,全局生效
Application.Current.Resources.Add(typeof(CustomButton), customButtonStyle);

如果不需要全局生效,也可以直接给单个CustomButton设置样式:

var button = new CustomButton();
button.Style = customButtonStyle; // 用上面创建的样式
button.Content = textBlock;
button.Focusable = false;
grid.Children.Add(button);

这样处理后,无论是鼠标悬停还是触摸操作,CustomButton都不会再出现高亮残留的问题。

内容的提问来源于stack exchange,提问作者user142914

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 16:15:40