代码之家  ›  专栏  ›  技术社区  ›  Matt Hamilton

WPF中的GroupBox标题是否会吞下鼠标单击?

  •  41
  • Matt Hamilton  · 技术社区  · 16 年前

    <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,它的头是一个复选框。我们都做过类似的事情——通常您会以这样一种方式绑定GroupBox的内容,即当复选框未选中时,它将被禁用。

    有人能复制这个吗?为什么会发生这种情况,有办法解决吗?

    4 回复  |  直到 16 年前
        1
  •  24
  •   Ray    14 年前

    Ian Oakes answer填充选项卡顺序,使标题位于内容之后。可以修改控件模板,使边框无法接收焦点。

    要执行此操作,请修改模板,使第二个和第三个边框(均位于轴网行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>
    
        2
  •  19
  •   Ian Oakes    16 年前

    原因是,具有BorderBrush TemplateBinding的另一个Border元素在可视化树中位于较低的位置,并捕获了鼠标单击,这就是为什么将BorderBrush设置为null允许复选框正确接收鼠标单击的原因。

    <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>
    
        3
  •  11
  •   Rune Andersen    14 年前

    我提出的另一个解决方案是在派生的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;
        }
      }
    }
    
        4
  •  4
  •   rudigrobler    16 年前

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

    我知道这违背了目标,但它确实证明了问题所在!