Does the GroupBox Header in WPF swallow mouse-clicks? Does the GroupBox Header in WPF swallow mouse-clicks? wpf wpf

Does the GroupBox Header in WPF swallow mouse-clicks?


Ian Oakes answer stuffs up the tab order such that the header comes after the content. It's possible to modify the control template such that the border can't receive focus.

To do this, modify the template so that the 2nd and 3rd borders (both in Grid Row 1) have IsHitTestVisible=false

Complete template below

<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>


It appears to be a subtle bug in the control template for the GroupBox. I found by editing the default template for the GroupBox and moving the Border named 'Header' to the last item in the control templates Grid element, the issue resolves itself.

The reason is that the one of the other Border elements with a TemplateBinding of BorderBrush was further down in the visual tree and was capturing the mouse click, that's why setting the BorderBrush to null allowed the CheckBox to correctly receive the mouse click.

Below is resulting style for the GroupBox. It is nearly identical to the default template for the control, except for the Border element named 'Header', which is now the last child of the Grid, rather than the second.

<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>


An alternative solution I made is implementing OnApplyTemplate in a derived GroupBox:

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;    }  }}