看一看这个非常简单的例子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>
所以我有一个分组框,其标题是一个复选框。 我们都做过这样的事情 - 通常你的分组框中的内容绑定以这样一种方式,它的时禁用复选框取消选中。
然而,当我运行该应用程序并点击复选框,我发现,我有时候鼠标点击被咽下去,CheckBox的状态不会改变。 如果我是正确的,当我点击像素的确切一行组框的上边框坐在的。
有人可以复制吗? 为什么这会发生,是有办法解决它?
编辑:组框的了borderThickness设置为0解决了这个问题,但显然它消除了边界,所以它看起来并不像一个分组框了。
这似乎是在组框控件模板个微妙的问题。 我发现通过编辑组框默认模板和移动边境命名为“头”到最后一个项目在控件模板网格元素,问题能否自行解决。
其原因是,与BorderBrush的TemplateBinding其他边界元素之一是在视觉树进一步向下,并捕获鼠标的点击,这就是为什么设置BorderBrush为NULL允许复选框以正确接收鼠标点击。
下面是导致该组框样式。 这几乎等同于控件的默认模板,除了命名为“头”的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>
伊恩·奥克斯答案充塞了标签次序,使得头自带的内容之后。 这是可能的修改控制模板,使得边框不能接收焦点。
要做到这一点,修改模板,以便在第二和第三边界(无论是在网格行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>
我提出另一种解决方案是在派生分组框中实施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;
}
}
}
如果你改变了分组框中的BorderBrush,它的作品!
<GroupBox BorderBrush="{x:Null}">
我知道这违背了客观,但它确实证明了问题所在!