如何通过纯代码方式禁用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
相关产品推荐
相关产品推荐

