Подтвердить что ты не робот

Заголовка GroupBox в WPF проглатывает щелчки мыши?

Посмотрите на этот очень простой пример программы 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 решает проблему, но, очевидно, она удаляет границу, поэтому она больше не выглядит как GroupBox.

4b9b3361

Ответ 1

Кажется, это тонкая ошибка в шаблоне управления для GroupBox. Я обнаружил, редактируя шаблон по умолчанию для GroupBox и перемещая границу с названием "Заголовок" на последний элемент в элементе элемента управления элемента решетки, проблема решает сам.

Причина в том, что один из других элементов Border с TemplateBinding BorderBrush был еще ниже в визуальном дереве и был захвачен щелчком мыши, поэтому для установки BorderBrush в null было разрешено CheckBox правильно получать щелчок мыши.

Ниже приводится стиль для GroupBox. Он почти идентичен шаблону по умолчанию для элемента управления, за исключением элемента Border с именем "Header", который теперь является последним дочерним элементом Grid, а не вторым.

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

Ответ 2

Ответ Ian Oakes набирает порядок табуляции, так что заголовок появляется после содержимого. Возможно изменить шаблон управления таким образом, чтобы граница не могла получать фокус.

Чтобы сделать это, измените шаблон так, чтобы 2-я и 3-я границы (как в Grid Row 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>

Ответ 3

Альтернативное решение, которое я сделал, - это реализовать OnApplyTemplate в производном 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;
    }
  }
}

Ответ 4

Если вы меняете GroupBox BorderBrush, он работает!

<GroupBox BorderBrush="{x:Null}">

Я знаю, что это побеждает цель, но это доказывает, где проблема!