前言
WPF的Button有一点特别奇怪的地方是
当您单击按钮的空白区域时,该按钮不会触发 Click 事件,因为该事件只会在按钮的可见内容区域内发生。
解决方式有两种
- 改变可见区域。
- 使用
PreviewMouseDown事件中触发Click事件。
推荐使用第一种方法,第二种按钮的悬浮样式依旧不会触发。
方式1
改变可见区域
核心代码
1 2 3 4 5 6 7 8 9
| <Button Content="My Button"> <Button.Template> <ControlTemplate TargetType="Button"> <Grid Background="Transparent"> <ContentPresenter /> </Grid> </ControlTemplate> </Button.Template> </Button>
|
就是在Button内部渲染区域的外层添加了一个Grid,并且设置背景色为Transparent。
优点奇葩的是
这个背景色必须设置,即使是设置的透明色,也算是可见区域了。
完整自定义按钮代码如下:
StyleZRoundButton.xaml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:ZView"> <Style x:Key="ZRoundButtonStyle" TargetType="{x:Type local:ZRoundButton}"> <Setter Property="OverridesDefaultStyle" Value="True" /> <Setter Property="Cursor" Value="Hand" /> <Setter Property="FocusVisualStyle" Value="{x:Null}" /> <Setter Property="HorizontalContentAlignment" Value="Center" /> <Setter Property="VerticalContentAlignment" Value="Center" /> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="Button"> <Grid Background="Transparent"> <Border Name="border" Padding="{TemplateBinding Padding}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="{Binding Path=BorderRadius, RelativeSource={RelativeSource TemplatedParent}}" IsHitTestVisible="True"> <ContentPresenter Margin="{TemplateBinding Padding}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" /> </Border> </Grid> <ControlTemplate.Triggers> <Trigger Property="IsMouseOver" Value="True"> <Setter Property="Opacity" Value="0.6" /> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style> </ResourceDictionary>
|
ZRoundButton.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| using System.Windows; using System.Windows.Controls;
namespace ZView { internal class ZRoundButton : Button { public int BorderRadius { get { return (int)GetValue(BorderRadiusProperty); } set { SetValue(BorderRadiusProperty, value); } }
public static readonly DependencyProperty BorderRadiusProperty = DependencyProperty.Register( "BorderRadius", typeof(int), typeof(ZRoundButton), new FrameworkPropertyMetadata() ); } }
|
方式2
要在单击按钮的任何位置时都触发 Click 事件,您可以使用 PreviewMouseDown 事件。该事件会在鼠标按下时触发,并在 Click 事件之前发生。
您可以通过以下方式将 PreviewMouseDown 事件处理程序绑定到按钮:
1
| <Button Content="My Button" PreviewMouseDown="Button_PreviewMouseDown" Click="Button_Click"/>
|
然后,在您的代码中实现 Button_PreviewMouseDown 和 Button_Click 事件处理程序。
在 Button_PreviewMouseDown 处理程序中,您可以使用以下代码触发 Click 事件:
1 2 3 4 5 6 7 8
| private void Button_PreviewMouseDown(object sender, MouseButtonEventArgs e) { if (e.ChangedButton == MouseButton.Left) { Button button = (Button)sender; button.RaiseEvent(new RoutedEventArgs(Button.ClickEvent)); } }
|
这将在单击按钮的任何位置时触发 Click 事件。
请注意,如果您希望仅在单击左键时触发 Click 事件,则可以使用上面示例代码中的 if 语句来检查 e.ChangedButton 的值。