如何在C#中的按钮上设置/更改/删除焦点样式?
我有几个按钮,我修改了它们的外观。我将它们设置为带有背景和自定义边框的平面按钮,因此它们看起来都非常漂亮,不再像普通按钮一样(实际上,它们现在看起来像Office 2003按钮;-)。这些按钮的边框为一个像素。
但是,当按钮被选中时(通过单击或者通过按下Tab键的键盘操作获得焦点),该按钮会突然获得一个额外的边框,并带有相同颜色的边框,因此使其成为两个像素的边框。此外,当我禁用一个像素边框时,按钮不会获得一个像素边框的焦点。
在网上,这个问题被问到很多类似"如何禁用按钮上的焦点"的问题,但这不是我想要的:焦点应该仍然存在,只是不能以现在的方式显示。
有什么建议? :-)
解决方案
当然,我们可以自己绘制按钮。状态标志之一被聚焦。
因此,在draw事件中,如果标志着重,请继续按照喜好绘制按钮,否则只需将其传递给base方法即可。
考虑为按钮实现自己的绘图代码。这样,我们就可以完全控制。过去,我实现了自己的Control派生,该控件派生自定义绘制按钮并实现所有按钮特性的目的,但是我们应该能够覆盖按钮的绘制并自己进行操作,从而控制按钮在每种状态下的绘制方式,包括重点关注时。
这是我们想要的效果吗?
public class NoFocusCueButton : Button { protected override bool ShowFocusCues { get { return false; } } }
我们可以像使用常规按钮一样使用此自定义按钮类,但是不会为我们提供额外的矩形焦点。
添加的第二个边框是Windows标准的"默认按钮"边框。我们可能已经注意到,如果我们在大多数对话框中使用多个按钮(例如任何"控制面板"属性窗口)进行制表,则原始的"双边框"按钮将变为"正常",而焦点对准的按钮将变为"双边框"。 "
这不一定专注于工作,而是通过按Enter键直观地指示所采取的操作。
在我看来,听起来好像我们并不真正在意内部工作。我们希望显示器不具有两个边界-完全可以理解。内部工作是为了解释为什么我们会看到此行为。现在...尝试修复它。
我要尝试的第一件事-记住,我还没有验证-是黑客。当按钮获得焦点时(从而获得双边框),请关闭单个边框。我们可能会得到想要的效果,而且非常简单。 (进入Focus事件。更好的是,子类为Button并重写OnFocus,然后将该子类用于将来的按钮。)
但是,这可能会带来新的,尴尬的视觉副作用。出于这种考虑,并且-因为骇客很少是最好的答案-我必须"正式"推荐其他人所说的话:自定义绘制按钮。尽管此处的代码可能有些过分,但CodeProject上的此链接讨论了如何执行此操作(VB链接;我们需要翻译)。我们应该在完全自定义模式下完全摆脱第二个边界。
还有另一种方法适合平面样式的按钮。不要使用按钮,而要使用标签。当我们完全替换按钮的UI时,无论使用按钮控件还是标签都无所谓。只需以相同的方式处理点击。
这对我很有用,尽管不是很好的实践,但这是一个不错的技巧,只要我们明显地命名按钮(并注释源代码),其他编码人员就会采纳这个想法。
瑞安
将FocusVisualStyle依赖项属性设置为样式中的null,并且虚线边框将消失。
来自MSDN:样式集中于控件和FocusVisualStyle
Windows Presentation Foundation (WPF) provides two parallel mechanisms for changing the visual appearance of a control when it receives keyboard focus. The first mechanism is to use property setters for properties such as IsKeyboardFocused within the style or template that is applied to the control. The second mechanism is to provide a separate style as the value of the FocusVisualStyle property; the "focus visual style" creates a separate visual tree for an adorner that draws on top of the control, rather than changing the visual tree of the control or other UI element by replacing it. This topic discusses the scenarios where each of these mechanisms is appropriate.
我们看到的额外边框是由FocusVisualStyle定义的,而不是在控件模板中定义的,因此我们需要删除或者覆盖样式以删除边框。
另一个选择(虽然有点怪异)是将事件处理程序添加到按钮的GotFocus事件。在该事件处理程序中,将False的值传递给按钮的NotifyDefault()
方法。因此,例如:
void myButton_GotFocus(object sender, EventArgs e) { myButton.NotifyDefault(false); }
我以为这每次都会起作用,但是我还没有对其进行广泛的测试。目前它对我有用,所以我对此感到满意。
如果我们有一个文本框和一个按钮
然后在文本框的textchange事件
写button1.focus();
会工作的。
制作一个自定义按钮:
public partial class CustomButton: Button { public ButtonPageButton() { InitializeComponent(); this.SetStyle(ControlStyles.Selectable, false); } }
那将摆脱那个烦人的边界! ;-)
我很幸运,仅将按钮的Focusable属性设置为false:
<Button HorizontalAlignment="Left" Margin="0,2" Command="{Binding OpenSuspendedJobCommand, Mode=OneWay}" Focusable="False" Style="{StaticResource ActionButton}" Content="Open Job..." />