Create Nested headers in WPF DataGrid

In WPF many times we may require to render a data grid which contains multilevel headers, for example we  have columns FirstName, LastName, Address1, Address2, City, State. Now we have to render a grid in which we have these columns these columns will have group name above the column header. It means there will be another level of header above these. In our case FirstName and LastName will be under Name, and Address1, Address2, City and State Columns will be under the Address.

Sample snapshot is displayed below.


XAML:



<Window x:Class="SuperHeaderExample.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:dg="clr-namespace:Microsoft.Windows.Controls;assembly=WpfToolkit"
        xmlns:tools="clr-namespace:Microsoft.Windows.Controls;assembly=WPFToolkit"
        xmlns:toolsp="clr-namespace:Microsoft.Windows.Controls.Primitives;assembly=WPFToolkit"
        xmlns:tools1="clr-namespace:System.Windows.Controls.Primitives;assembly=PresentationFramework"
        Title="MainWindow"
Height="350" Width="900">
   
<Window.Resources>
        <LinearGradientBrush x:Key="HeaderBrush" StartPoint="0.5,0" EndPoint="0.5,1">
    
       <GradientStop Color="#FF6B8E95" Offset="0"/>
            <GradientStop Color="#FF14A7C1" Offset="1"/>
            <GradientStop Color="#FF1E424E" Offset="0.509"/>
            <GradientStop Color="#FF1D4855" Offset="0.542"/>
            <GradientStop Color="#FF1D4855" Offset="0.542"/>
            <GradientStop Color="#FF193A44" Offset="0.526"/>
        </LinearGradientBrush>


      <LinearGradientBrush x:Key="HeaderBorderBrush" StartPoint="0.5,0" EndPoint="0.5,1">
            <GradientStop Color="#FF1D1D1D" Offset="0.614"/>
            <GradientStop Color="#FF007F96" Offset="0.853"/>
            <GradientStop Color="#FF0AEAFA" Offset="1"/>
        </LinearGradientBrush>
        <Style x:Key="HeaderStyle" TargetType="{x:Type toolsp:DataGridColumnHeader}">
            <Setter Property="Background" Value="{StaticResource HeaderBrush}" />
            <Setter Property="Foreground" Value="White"/>
            <Setter Property="BorderBrush" Value="{StaticResource HeaderBorderBrush}" />
 
          <Setter Property="BorderThickness" Value="1" />
            <Setter Property="SnapsToDevicePixels" Value="True" />
            <Setter Property="HorizontalAlignment" Value="Stretch"/>
            <Setter Property="MinWidth" Value="0" />
            <Setter Property="MinHeight" Value="30" />
            <Setter Property="Cursor" Value="Hand" />
        </Style>
   
</Window.Resources>
   
<StackPanel>
   
<Grid>
            <ScrollViewer VerticalScrollBarVisibility="Hidden" HorizontalScrollBarVisibility="Auto" HorizontalAlignment="Left" Height="300">
                <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="auto"/>
                <RowDefinition Height="2*"/>
            </Grid.RowDefinitions>
                    <Grid Grid.Row="0" Width="{Binding Path=Width, ElementName=datagrid1}" HorizontalAlignment="Left" Margin="0 0 0 0">
     <Grid.ColumnDefinitions>
        <ColumnDefinition Width="{Binding ElementName=Column1, Path=ActualWidth}"/>
        <ColumnDefinition Width="{Binding ElementName=Column2, Path=ActualWidth}"/>
        <ColumnDefinition Width="{Binding ElementName=Column3, Path=ActualWidth}"/>
        <ColumnDefinition Width="{Binding ElementName=Column4, Path=ActualWidth}"/>
        <ColumnDefinition Width="{Binding ElementName=Column5, Path=ActualWidth}"/>
        <ColumnDefinition Width="{Binding ElementName=Column6, Path=ActualWidth}"/>
        <ColumnDefinition Width="{Binding ElementName=Column7, Path=ActualWidth}"/>
    </Grid.ColumnDefinitions>
    <Border Grid.Column="1" Grid.ColumnSpan="2" BorderBrush="Gray" HorizontalAlignment="Stretch" BorderThickness="1">
     <Label Name='Name' HorizontalContentAlignment='Stretch' Foreground="White" TextBlock.FontWeight='Bold' TextBlock.FontFamily='Segoe UI' Background="{StaticResource HeaderBrush}" BorderBrush="{StaticResource HeaderBorderBrush}">Name</Label>
    </Border>
    <Border Grid.Column="3" Grid.ColumnSpan="4" BorderBrush="Gray" HorizontalAlignment="Stretch" BorderThickness="1">
    <Label Name='Address' HorizontalContentAlignment='Stretch' Foreground="White" TextBlock.FontWeight='Bold' TextBlock.FontFamily='Segoe UI' Background="{StaticResource HeaderBrush}" BorderBrush="{StaticResource HeaderBorderBrush}">Address</Label>                        </Border>
</Grid>
<tools:DataGrid AutoGenerateColumns="False" Name="datagrid1" Grid.Row="1" RowHeaderWidth="0" HorizontalAlignment="Left"
ScrollViewer.CanContentScroll="False" ScrollViewer.HorizontalScrollBarVisibility="Hidden" ColumnHeaderStyle="{DynamicResource HeaderStyle}" ItemsSource="{Binding Path=WPIData}">    <tools:DataGrid.Columns>
  <tools:DataGridTextColumn Header="S.No" MinWidth="80" x:Name="Column1" Binding="{Binding Path=Column1}"/>
  <tools:DataGridTextColumn Header="First Name" MinWidth="100" x:Name="Column2" Binding="{Binding Path=Column2}"/>
  <tools:DataGridTextColumn Header="Last Name" MinWidth="100" x:Name="Column3" Binding="{Binding Path=Column3}"/>
  <tools:DataGridTextColumn Header="Address 1" MinWidth="90" x:Name="Column4" Binding="{Binding Path=Column4}" />
  <tools:DataGridTextColumn Header="Address 2" MinWidth="90" x:Name="Column5" Binding="{Binding Path=Column5}" />
  <tools:DataGridTextColumn Header="City" MinWidth="90" x:Name="Column6" Binding="{Binding Path=Column6}" />
  <tools:DataGridTextColumn Header="State" MinWidth="90" x:Name="Column7" Binding="{Binding Path=Column7}" />
 </tools:DataGrid.Columns>
 </tools:DataGrid>
</Grid>
</ScrollViewer>
</Grid>
</StackPanel>
</Window>