I know I'm very late to the party on this one but... here's a fairly robust, if not rather more complicated than it should be, like a lot of things in WPF, answer.
Firstly, I'm not sure why there isn't a just a CornerRadius
property on the GroupBox
control itself. It feels like that could have been implemented quite easily.
Secondly, the reason you can't just create a Style
that targets the CornerRadius
of Border
controls in the GroupBox
is, when you look at how the framework composes a GroupBox
from other controls, the CornerRadius
properties of the Border
controls it uses are hard set to the value 2
. i.e. they can't be overridden by a Style
element.
To See how the WPF team originally created the GroupBox
control, and to use this as a base for a square-corned GroupBox
, right-click on one in the designer and select Edit Template
then Edit a Copy...
. This will then create a Style
which targets GroupBox
and overrides its default Template
with a copy of exactly how the GroupBox
control is normally composed. It will create something like the below. The simplest thing to do next is to go through and change all the CornerRadius
elements to 0
and then reference the style as such: <GroupBox Header="Blah" Style="{StaticResource SquareCornerGroupBox}" />
<BorderGapMaskConverter x:Key="BorderGapMaskConverter"/>
<Style x:Key="SquareCornerGroupBox" 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.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 Background="{TemplateBinding Background}" BorderBrush="Transparent" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="4" Grid.Column="0" Grid.ColumnSpan="4" Grid.RowSpan="3" Grid.Row="1"/>
<Border BorderBrush="White" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="4" Grid.ColumnSpan="4" Grid.RowSpan="3" Grid.Row="1">
<Border.OpacityMask>
<MultiBinding ConverterParameter="7" Converter="{StaticResource BorderGapMaskConverter}">
<Binding ElementName="Header" Path="ActualWidth"/>
<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" Padding="3,1,3,0" Grid.RowSpan="2" Grid.Row="0">
<ContentPresenter ContentSource="Header" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</Border>
<ContentPresenter Grid.Column="1" Grid.ColumnSpan="2" Margin="{TemplateBinding Padding}" Grid.Row="2" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>