#895 – Adding a Watermark to a GroupBox

Here’s an example of changing a GroupBox so that the Header element becomes a rotated watermark.

To do this, you modify the default template for the GroupBox.  We change the ContentPresenter for the header to appear in the middle of the parent Grid and we rotate it.

        <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.ColumnDefinitions>
                                <ColumnDefinition Width="6"/>
                                <ColumnDefinition Width="*"/>
                                <ColumnDefinition Width="6"/>
                            </Grid.ColumnDefinitions>
                            <Grid.RowDefinitions>
                                <RowDefinition Height="Auto"/>
                                <RowDefinition Height="Auto"/>
                                <RowDefinition Height="*"/>
                                <RowDefinition Height="6"/>
                            </Grid.RowDefinitions>
                            <Border BorderBrush="Transparent" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Grid.ColumnSpan="3" Grid.Column="0" CornerRadius="4" Grid.Row="1" Grid.RowSpan="3"/>
                            <ContentPresenter Grid.Column="1" Margin="{TemplateBinding Padding}" Grid.Row="2" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                            <ContentPresenter ContentSource="Header" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
                                              Grid.Row="1" Grid.RowSpan="2" Grid.Column="1"
                                              HorizontalAlignment="Center" VerticalAlignment="Center"
                                              RenderTransformOrigin="0.5,0.5">
                                <ContentPresenter.RenderTransform>
                                    <RotateTransform Angle="45"/>
                                </ContentPresenter.RenderTransform>
                            </ContentPresenter>
                            <Border BorderBrush="White" BorderThickness="{TemplateBinding BorderThickness}" Grid.ColumnSpan="3" CornerRadius="4" Grid.Row="1" Grid.RowSpan="3">
                                <Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="3">
                                    <Border BorderBrush="White" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="2"/>
                                </Border>
                            </Border>
                        </Grid>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

Below, we use the new style in a GroupBox and specify a header to use for the watermark.

    <GroupBox Margin="10" Style="{DynamicResource GroupBoxStyle1}">
        <GroupBox.Header>
            <Label Content="Roman Guys" FontSize="36"
                   Opacity="0.3" Foreground="MediumBlue"/>
        </GroupBox.Header>
        <StackPanel>
          <!-- Content here -->
        </StackPanel>
    </GroupBox>

895-001

#894 – Creating a GroupBox with a Header But No Border

There are cases where you might want a GroupBox for grouping a set of child controls, but without the visual border around the controls.  You can retain the header element, but remove the border of a GrouBox by setting the BorderBrush property to Transparent.

    <GroupBox Margin="10" Header="Roman Guys" BorderBrush="Transparent">
        <StackPanel>
            <StackPanel Orientation="Horizontal">
                <Image Source="Augustus.jpg" Height="100" Margin="5"/>
                <TextBlock Text="Augustus" VerticalAlignment="Center"/>
            </StackPanel>
            <StackPanel Orientation="Horizontal">
                <Image Source="Tiberius.jpg" Height="100" Margin="5"/>
                <TextBlock Text="Tiberius" VerticalAlignment="Center"/>
            </StackPanel>
            <StackPanel Orientation="Horizontal">
                <Image Source="Caligula.jpeg" Height="100" Margin="5"/>
                <TextBlock Text="Caligula" VerticalAlignment="Center"/>
            </StackPanel>
        </StackPanel>
    </GroupBox>

894-001

#893 – Creating a GroupBox with a Border But No Header

There are cases where you might want a GroupBox for grouping a set of child controls, but without the associated header text.  If you try just omitting the Header, but you’ll see a little gap at the top of the GroupBox.

893-001

To remove the gap you could just use a Border element instead of a GroupBox, changing its style to match the GroupBox.  You can also edit the default style of the GroupBox.

To edit the style of the GroupBox, start by right-clicking the GroupBox control in Visual Studio and select Edit TemplateEdit a Copy.

893-002

Accept the default name for the style.

893-003

Within the Style element, find the OpacityMask, near the bottom, and comment it out.

894-004

Note that your GroupBox element is now using your modified copy of the style.

    <GroupBox Margin="10" BorderBrush="DarkGray"
              Style="{DynamicResource GroupBoxStyle1}">

The GroupBox will no longer have the little gap where the header should go.
893-005

#892 – Changing the Font for Everything within a GroupBox

If you want to change the font used for both the header of a GroupBox, as well as any textual elements within it, you can set font-related properties on the GroupBox itself.

In the example below, the GroupBox on the left does not set font properties:

<GroupBox Header="Roman Dudes" Margin="10">

The GroupBox on the right sets both FontSize and FontFamily:

        <GroupBox Header="Greek Dudes" Margin="10"
                  FontSize="16" FontFamily="Comic Sans MS">

The GroupBox on the right then uses the specified font for both the header and for any Label elements within its boundaries.
892-001

#891 – Changing the Border of a GroupBox

You can easily change the border drawn around a GroupBox control by setting its BorderThickness and BorderBrush properties.

<GroupBox Header="Roman Dudes" Margin="10"
          BorderThickness="2" BorderBrush="Purple">
    <StackPanel>
        <StackPanel Orientation="Horizontal">
            <Image Source="Augustus.jpg" Height="100" Margin="5"/>
            <TextBlock Text="Augustus" VerticalAlignment="Center"/>
        </StackPanel>
        <StackPanel Orientation="Horizontal">
            <Image Source="Tiberius.jpg" Height="100" Margin="5"/>
            <TextBlock Text="Tiberius" VerticalAlignment="Center"/>
        </StackPanel>
        <StackPanel Orientation="Horizontal">
            <Image Source="Caligula.jpeg" Height="100" Margin="5"/>
            <TextBlock Text="Caligula" VerticalAlignment="Center"/>
        </StackPanel>
    </GroupBox>

891-001

#856 – Placing RadioButtons in a GroupBox

When including a group of RadioButton controls in your application, it’s common to put them in a GroupBox.  This makes the grouping visible to a customer.

A related group of RadioButtons are normally placed in a panel control, to allow the grouping logic to work correctly.  (Only one RadioButton at a time is selected within the group).  Because a GroupBox is a ContentControl, rather than a Panel, you’ll want to place a panel within the GroupBox and then place the related RadioButtons within the panel.

        <GroupBox Header="Gender">
            <StackPanel Margin="10">
                <RadioButton Content="Male"/>
                <RadioButton Content="Female"/>
            </StackPanel>
        </GroupBox>

        <GroupBox Header="Height">
            <StackPanel Margin="10">
                <RadioButton Content="Tall"/>
                <RadioButton Content="Short"/>
            </StackPanel>
        </GroupBox>

856-001

#835 – Displaying Custom Content in a GroupBox Header

You normally set the Header property of a GroupBox to some text.

        <GroupBox Header="Julius Caesar">
            <Label Content="100BC - 44BC, etc."/>
        </GroupBox>
        <GroupBox Header="Augustus">
            <Label Content="63BC - 14AD, etc."/>
        </GroupBox>

835-001

You can, however, set the Header to anything that you like, including a panel containing other controls.

        <GroupBox>
            <GroupBox.Header>
                <StackPanel Orientation="Horizontal">
                    <Label Content="Julius Caesar"/>
                    <Image Source="Caesar.jpg" Height="48"/>
                </StackPanel>
            </GroupBox.Header>
            <Label Content="100BC - 44BC, etc."/>
        </GroupBox>
        <GroupBox>
            <GroupBox.Header>
                <StackPanel Orientation="Horizontal">
                    <Label Content="Augustus"/>
                    <Image Source="Augustus.jpg" Height="48"/>
                </StackPanel>
            </GroupBox.Header>
            <Label Content="63BC - 14AD, etc."/>
        </GroupBox>

835-002

#506 – Using a ComboBox as GroupBox Header

Because the GroupBox.Header property can be set to any object, you could host a control in the header of the GroupBox.  In the example below, we specify a ComboBox for the Header and then bind the various fields to the selected item.

    <GroupBox Margin="15">
        <GroupBox.Header>
            <ComboBox Name="cboDogs" ItemsSource="{Binding Dogs}" DisplayMemberPath="Name"
                      SelectedIndex="0"
                      SelectedValue="{Binding SelectedDog}"
                      SelectedValuePath=""/>
        </GroupBox.Header>
        <Grid Margin="10" DataContext="{Binding SelectedDog}">
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="Auto"/>
                <RowDefinition/>
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <ColumnDefinition/>
                <ColumnDefinition/>
            </Grid.ColumnDefinitions>

            <Label Grid.Row="0" Grid.Column="0" Content="Name:" FontWeight="Bold" HorizontalAlignment="Right"/>
            <Label Grid.Row="0" Grid.Column="1" Content="{Binding Name}"/>
            <Label Grid.Row="1" Grid.Column="0" Content="Age:" FontWeight="Bold" HorizontalAlignment="Right"/>
            <Label Grid.Row="1" Grid.Column="1" Content="{Binding Age}" />
            <Label Grid.Row="2" Grid.Column="0" Content="Hobby:" FontWeight="Bold" HorizontalAlignment="Right"/>
            <Label Grid.Row="2" Grid.Column="1" Content="{Binding Hobby}"/>
        </Grid>
    </GroupBox>
    public partial class Window1 : Window, INotifyPropertyChanged
    {
        public Window1()
        {
            InitializeComponent();
            this.DataContext = this;

            Dogs = new ObservableCollection<Dog>();
            Dogs.Add(new Dog("Lassie", 12, "Saving people"));
            Dogs.Add(new Dog("Rin Tin Tin", 52, "War dog"));
            Dogs.Add(new Dog("Benji", 18, "Befriends strays"));
            OnPropertyChanged("Dogs");
        }

        public ObservableCollection<Dog> Dogs { get; protected set; }

        private Dog selectedDog;
        public Dog SelectedDog {
            get
            {
                return selectedDog;
            }
            set
            {
                if (value != selectedDog)
                {
                    selectedDog = value;
                    OnPropertyChanged("SelectedDog");
                }
            }
        }

        public event PropertyChangedEventHandler PropertyChanged = delegate { };

        private void OnPropertyChanged(string prop)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(prop));
        }
    }

#505 – The Header of a GroupBox Can Be Anything

The Header property of a GroupBox control specifies the content to be displayed along the top border of the GroupBox.  This is often a text string, specified in XAML.  But similar to the Content property of a content control, the Header property can be set to any object.

In the example below, Header is set to a Label, which then allows more control over how the Label will appear than if just a text string had been used.

    <GroupBox Margin="15">
        <GroupBox.Header>
            <Label FontWeight="Bold" FontFamily="Georgia" FontSize="16"  Content="Dog Info"/>
        </GroupBox.Header>
        <Grid Margin="10">
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="Auto"/>
                <RowDefinition/>
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <ColumnDefinition/>
                <ColumnDefinition/>
            </Grid.ColumnDefinitions>

            <Label Grid.Row="0" Grid.Column="0" Content="Name:" FontWeight="Bold" HorizontalAlignment="Right"/>
            <Label Grid.Row="0" Grid.Column="1" Content="Kirby"/>
            <Label Grid.Row="1" Grid.Column="0" Content="Age:" FontWeight="Bold" HorizontalAlignment="Right"/>
            <Label Grid.Row="1" Grid.Column="1" Content="15" />
            <Label Grid.Row="2" Grid.Column="0" Content="Hobby:" FontWeight="Bold" HorizontalAlignment="Right"/>
            <Label Grid.Row="2" Grid.Column="1" Content="Chasing balls"/>
        </Grid>
    </GroupBox>

#504 – GroupBox Basics

GroupBox is a control that draws a labeled border around a single child element.  Being a content control, it can contain at most one child element, but the child can be a panel control which in turn contains a number of other controls.

The GroupBox is typically used to show visually that a set of child controls are related.

The example below shows a GroupBox that contains a Grid as its child element.  The Grid then contains some Labels.

    <GroupBox Header="Dog Info" Margin="15">
        <Grid Margin="10">
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="Auto"/>
                <RowDefinition/>
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <ColumnDefinition/>
                <ColumnDefinition/>
            </Grid.ColumnDefinitions>

            <Label Grid.Row="0" Grid.Column="0" Content="Name:" FontWeight="Bold" HorizontalAlignment="Right"/>
            <Label Grid.Row="0" Grid.Column="1" Content="Kirby"/>
            <Label Grid.Row="1" Grid.Column="0" Content="Age:" FontWeight="Bold" HorizontalAlignment="Right"/>
            <Label Grid.Row="1" Grid.Column="1" Content="15" />
            <Label Grid.Row="2" Grid.Column="0" Content="Hobby:" FontWeight="Bold" HorizontalAlignment="Right"/>
            <Label Grid.Row="2" Grid.Column="1" Content="Chasing balls"/>
        </Grid>
    </GroupBox>