WPF中的GroupBox标题是否会吞下鼠标点击?
看看这个非常简单的例子WPF程序:
<Window x:Class="WpfApplication1.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Window1" Height="300" Width="300"> <GroupBox> <GroupBox.Header> <CheckBox Content="Click Here"/> </GroupBox.Header> </GroupBox> </Window>
所以我有一个GroupBox的头是CheckBox。 我们都做了这样的事情 – 通常你绑定的GroupBox的内容,这样的方式,当CheckBox被取消选中时被禁用。
但是,当我运行这个应用程序,并点击checkbox,我发现有时候我的鼠标点击被吞下,CheckBox的状态不会改变。 如果我是正确的,那就是当我点击GroupBox顶部边框所在的像素行时。
有人可以复制这个? 为什么会发生这种情况,有没有办法解决这个问题?
编辑:设置GroupBox的BorderThickness为0解决了这个问题,但显然它删除了边框,所以它看起来不再像combobox了。
这似乎是GroupBox的控件模板中的一个微妙的错误。 我发现通过编辑GroupBox的默认模板并将名为“Header”的边框移动到控件模板Grid元素的最后一项,问题就可以解决。
原因是BorderBrush的TemplateBinding的其他Border元素之一是在视觉树中进一步下降,并捕获鼠标点击,这就是为什么设置BorderBrush为null允许CheckBox正确接收鼠标点击。
以下是GroupBox的结果样式。 它与控件的默认模板几乎相同,除了名为“Header”的Border元素,它现在是网格的最后一个子元素,而不是第二个元素。
<BorderGapMaskConverter x:Key="BorderGapMaskConverter"/> <Style x:Key="GroupBoxStyle1" TargetType="{x:Type GroupBox}"> <Setter Property="BorderBrush" Value="#D5DFE5"/> <Setter Property="BorderThickness" Value="1"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type GroupBox}"> <Grid SnapsToDevicePixels="true"> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> <RowDefinition Height="*"/> <RowDefinition Height="6"/> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="6"/> <ColumnDefinition Width="Auto"/> <ColumnDefinition Width="*"/> <ColumnDefinition Width="6"/> </Grid.ColumnDefinitions> <Border Grid.Column="0" Grid.ColumnSpan="4" Grid.Row="1" Grid.RowSpan="3" Background="{TemplateBinding Background}" BorderBrush="Transparent" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="4"/> <ContentPresenter Margin="{TemplateBinding Padding}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" Grid.Column="1" Grid.ColumnSpan="2" Grid.Row="2"/> <Border Grid.ColumnSpan="4" Grid.Row="1" Grid.RowSpan="3" BorderBrush="White" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="4"> <Border.OpacityMask> <MultiBinding Converter="{StaticResource BorderGapMaskConverter}" ConverterParameter="7"> <Binding Path="ActualWidth" ElementName="Header"/> <Binding Path="ActualWidth" RelativeSource="{RelativeSource Self}"/> <Binding Path="ActualHeight" RelativeSource="{RelativeSource Self}"/> </MultiBinding> </Border.OpacityMask> <Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="3"> <Border BorderBrush="White" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="2"/> </Border> </Border> <Border x:Name="Header" Grid.Column="1" Grid.Row="0" Grid.RowSpan="2" Padding="3,1,3,0"> <ContentPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" ContentSource="Header" RecognizesAccessKey="True"/> </Border> </Grid> </ControlTemplate> </Setter.Value> </Setter> </Style>
伊恩·奥克斯(Ian Oakes)回答了这个标签顺序的问题,以便标题在内容之后。 可以修改控件模板,使边框无法获得焦点。
为此,请修改模板,使第二个和第三个边框(都在网格行1中)具有IsHitTestVisible=false
完整的模板如下
<BorderGapMaskConverter x:Key="GroupBoxBorderGapMaskConverter" /> <Style x:Key="{x:Type GroupBox}" TargetType="{x:Type GroupBox}"> <Setter Property="Control.BorderBrush" Value="#FFD5DFE5" /> <Setter Property="Control.BorderThickness" Value="1" /> <Setter Property="Control.Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type GroupBox}"> <Grid SnapsToDevicePixels="True"> <Grid.ColumnDefinitions> <ColumnDefinition Width="6" /> <ColumnDefinition Width="Auto" /> <ColumnDefinition Width="*" /> <ColumnDefinition Width="6" /> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition Height="Auto" /> <RowDefinition Height="*" /> <RowDefinition Height="6" /> </Grid.RowDefinitions> <Border Name="Header" Padding="3,1,3,0" Grid.Row="0" Grid.RowSpan="2" Grid.Column="1"> <ContentPresenter ContentSource="Header" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}" /> </Border> <Border CornerRadius="4" Grid.Row="1" Grid.RowSpan="3" Grid.Column="0" Grid.ColumnSpan="4" BorderThickness="{TemplateBinding Control.BorderThickness}" BorderBrush="#00FFFFFF" Background="{TemplateBinding Control.Background}" IsHitTestVisible="False" /> <ContentPresenter Grid.Row="2" Grid.Column="1" Grid.ColumnSpan="2" Margin="{TemplateBinding Control.Padding}" SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}"/> <Border CornerRadius="4" Grid.Row="1" Grid.RowSpan="3" Grid.ColumnSpan="4" BorderThickness="{TemplateBinding Control.BorderThickness}" BorderBrush="#FFFFFFFF" IsHitTestVisible="False"> <UIElement.OpacityMask> <MultiBinding Converter="{StaticResource GroupBoxBorderGapMaskConverter}" ConverterParameter="7"> <Binding ElementName="Header" Path="ActualWidth" /> <Binding Path="ActualWidth" RelativeSource="{RelativeSource Self}" /> <Binding Path="ActualHeight" RelativeSource="{RelativeSource Self}" /> </MultiBinding> </UIElement.OpacityMask> <Border BorderThickness="{TemplateBinding Control.BorderThickness}" BorderBrush="{TemplateBinding Control.BorderBrush}" CornerRadius="3"> <Border BorderThickness="{TemplateBinding Control.BorderThickness}" BorderBrush="#FFFFFFFF" CornerRadius="2" /> </Border> </Border> </Grid> </ControlTemplate> </Setter.Value> </Setter> </Style>
我做的另一个解决scheme是在派生的GroupBox中实现OnApplyTemplate:
public override void OnApplyTemplate() { base.OnApplyTemplate(); if (Children.Count == 0) return; var grid = GetVisualChild(0) as Grid; if (grid != null && grid.Children.Count > 3) { var bd = grid.Children[3] as Border; if (bd != null) { bd.IsHitTestVisible = false; } } }
如果您更改GroupBox的BorderBrush,它的工作原理!
<GroupBox BorderBrush="{x:Null}">
我知道这打破了目标,但它确实certificate问题在哪里!