Grouping in WPF DataGrid (SfDataGrid)

16 Oct 202324 minutes to read

WPF DataGrid allows you to group the data against one or more columns. When grouping is applied, the data is organized into a hierarchical structure based on matching column values and it is sorted by ascending order.

SfDataGrid allows you to group the data in below ways,

  • UI Grouping
  • Programmatic Grouping

UI grouping

You can allow end-user to group the data by setting SfDataGrid.AllowGrouping property to true , where user can drag and drop the column into GroupDropArea to group based on that column.

When the column is grouped, records that have an identical value in the column are combined to form a group. The GroupDropArea can be enabled by setting the SfDataGrid.ShowGroupDropArea property to true.

<syncfusion:SfDataGrid  x:Name="dataGrid"
                        AllowGrouping="False"
                        AutoGenerateColumns="True"
                        ItemsSource="{Binding Orders}"
                        ShowGroupDropArea="True" />
this.dataGrid.AllowGrouping = true;

You can enable or disable grouping on particular column by setting the GridColumn.AllowGrouping property.

<syncfusion:SfDataGrid  x:Name="dataGrid"
                        AutoGenerateColumns="False"
                        ItemsSource="{Binding Orders}"
                        ShowGroupDropArea="True">
    <syncfusion:SfDataGrid.Columns>
        <syncfusion:GridTextColumn AllowGrouping="True" MappingName="OrderID" />
        <syncfusion:GridTextColumn AllowGrouping="False" MappingName="CustomerID" />        
    </syncfusion:SfDataGrid.Columns>
</syncfusion:SfDataGrid>
this.dataGrid.Columns["OrderID"].AllowGrouping = true;
this.dataGrid.Columns["CustomerID"].AllowGrouping = true;

NOTE

GridColumn.AllowGrouping takes higher priority than SfDataGrid.AllowGrouping.

WPF DataGrid Grouping

The data can be grouped by an unlimited number of columns. To group more than one columns, drag-and-drop the desired columns in to GroupDropArea.

Multiple Grouping in WPF DataGrid

Each group is identified by its CaptionSummaryRows and it is used to organize the data into a hierarchical tree structure based on identical values of that column. The underlying records in each caption summary row can be expanded or collapsed by clicking its group caption.

Each CaptionSummaryRow carries information about a particular group like group name, number of items (records) in the group, etc. You can refer Caption Summaries section, for more information about CaptionSummaryRow.

Programmatic grouping

The WPF DataGrid (SfDataGrid) allows you to group the data programmatically by adding or removing GroupColumnDescription to SfDataGrid.GroupColumnDescriptions collection.

For example, if you want to group the OrderID column programmatically, define its MappingName to ColumnName property of GroupColumnDescription. Then add the GroupColumnDescription to the SfDataGrid.GroupColumnDescriptions collection.

<syncfusion:SfDataGrid  x:Name="dataGrid"
                        AutoGenerateColumns="True"
                        ItemsSource="{Binding Orders}"
                        ShowGroupDropArea="True">
    <syncfusion:SfDataGrid.GroupColumnDescriptions>
        <syncfusion:GroupColumnDescription ColumnName="OrderID" />
    </syncfusion:SfDataGrid.GroupColumnDescriptions>
</syncfusion:SfDataGrid>
this.dataGrid.GroupColumnDescriptions.Add(new GroupColumnDescription() { ColumnName = "OrderID" });

You can group more than one column programmatically.

<syncfusion:SfDataGrid x:Name="dataGrid"                               
                        ItemsSource="{Binding Orders}"
                        ShowGroupDropArea="True">

    <syncfusion:SfDataGrid.GroupColumnDescriptions>
        <syncfusion:GroupColumnDescription ColumnName="OrderID" />
        <syncfusion:GroupColumnDescription ColumnName="CustomerID" />
    </syncfusion:SfDataGrid.GroupColumnDescriptions>

</syncfusion:SfDataGrid>
this.dataGrid.View.BeginInit();
this.dataGrid.GroupColumnDescriptions.Add(new GroupColumnDescription() { ColumnName = "OrderID" });
this.dataGrid.GroupColumnDescriptions.Add(new GroupColumnDescription() { ColumnName = "CustomerID" });
this.dataGrid.View.EndInit();

Group based on display text

You can group the column in DataGrid based on the value being displayed in cell by setting GridColumn.GroupMode as Display.
In the below example, OrderID column displays value with one decimal digit in cell. But when you group, groups will be created based on actual value considering all decimal digits of value (Refer right side screen shot). You can group based value displayed in the cell by setting GridColumn.GroupMode as Display (Refer left side screen shot for the same data).

<Syncfusion:GridNumericColumn NumberDecimalDigits="1" MappingName="OrderID" HeaderText="OrderID" GroupMode="Display"/>
this.datagrid.Columns["OrderID"].GroupMode = DataReflectionMode.Display;

Grouped Column in WPF DataGrid based on Display Text

Group caption based on DisplayMember when grouping GridComboBoxColumn and GridMultiColumnDropDownList

In WPF DataGrid (SfDataGrid), you can group the column based on display value and also the same can be displayed in caption summary by setting GridColumn.GroupMode as Display.

<Syncfusion:GridComboBoxColumn ItemsSource="{Binding ComboItemsSource}" MappingName="ShipId" DisplayMemberPath="ShipCity" SelectedValuePath="ShipId" GroupMode="Display"/>
this.datagrid.Columns.Add(new GridComboBoxColumn()
{
    ItemsSource = viewModel.ComboItemsSource,
    DisplayMemberPath = "ShipCity",
    MappingName = "ShipId",
    SelectedValuePath = "ShipId",
    GroupMode = DataReflectionMode.Display
});

Grouped Column in WPF DataGrid based on Display Member

Clearing or removing group

You can remove all the groups by clearing SfDataGrid.GroupColumnDescriptions collection.

this.dataGrid.GroupColumnDescriptions.Clear();

You can ungroup the column programmatically at runtime by removing GroupColumnDescription from SfDataGrid.GroupColumnDescriptions collection.

this.dataGrid.View.BeginInit();            
this.dataGrid.GroupColumnDescriptions.Remove(this.dataGrid.GroupColumnDescriptions[0]);
this.dataGrid.View.EndInit();

To ungroup the column in UI, click the close button on column header or drag the column header from the GroupDropArea and drop it on the header row.

WPF DataGrid Column without Grouping

Hiding the column when grouped

You can hide the column header when the particular column gets grouped by setting SfDataGrid.ShowColumnWhenGrouped property to false.

<syncfusion:SfDataGrid  x:Name="dataGrid"
                        AutoGenerateColumns="True"
                        ItemsSource="{Binding Orders}"
                        ShowColumnWhenGrouped="False"
                        ShowGroupDropArea="True" />
this.dataGrid.ShowColumnWhenGrouped = false;

Hide Grouping Column in WPF DataGrid

Freezing caption rows when scrolling

You can freeze the group caption of the group in view until its records scrolled out of the view by setting the SfDataGrid.AllowFrozenGroupHeaders property to true.

<syncfusion:SfDataGrid  x:Name="dataGrid"                            
                        AutoGenerateColumns="True"
                        AllowFrozenGroupHeaders="True"
                        ItemsSource="{Binding Orders}"
                        ShowGroupDropArea="True" />
this.dataGrid.AllowFrozenGroupHeaders = true;

WPF DataGrid with Frozen Caption Summary Rows

Expanding or collapsing the groups

By default, you can view the records in each group by expanding or collapsing its group caption.

You can allow end-user to expand or collapse the groups programmatically at runtime.

Expand groups while grouping

You can expand all the groups while grouping by setting SfDataGrid.AutoExpandGroups to true. So, when user group any column, then all groups will be in expanded state.

<syncfusion:SfDataGrid  x:Name="dataGrid"
                        AutoExpandGroups="True"
                        AutoGenerateColumns="True"
                        ItemsSource="{Binding Orders}"
                        ShowGroupDropArea="True" />
this.dataGrid.AutoExpandGroups = true;

Programmatically expand or collapse the groups

Expand or collapse all the Groups

You can expand or collapse all the groups at programmatically at runtime by using SfDataGrid.ExpandAllGroup and SfDataGrid.CollapseAllGroup methods.

this.dataGrid.ExpandAllGroup();
this.dataGrid.CollapseAllGroup();

Expand or Collapse the Group based on its level

You can expand or collapse the group based on its level by using SfDataGrid.ExpandGroupsAtLevel and SfDataGrid.CollapseGroupsAtLevel methods.

this.dataGrid.ExpandGroupsAtLevel(2);
this.dataGrid.CollapseGroupsAtLevel(2);

Expand or Collapse the specific Group

You can expand or collapse specific group by using SfDataGrid.ExpandGroup and SfDataGrid.CollapseGroup methods.

var group = (dataGrid.View.Groups[0] as Group);
this.dataGrid.ExpandGroup(group);
this.dataGrid.CollapseGroup(group);

Customize indent column width

You can customize the width of IndentColumn in SfDataGrid by using IndentColumnWidth property as like below.

<Syncfusion:SfDataGrid x:Name="dataGrid"                                      
                       AllowGrouping="True"
                       IndentColumnWidth="50"
                       ShowGroupDropArea="True"
                       ItemsSource="{Binding OrderInfoCollection }">
this.dataGrid.IndentColumnWidth = 50;

GroupDropArea customization

GroupDropArea text

You can change the GroupDropArea’ s text can by setting SfDataGrid.GroupDropAreaText property.

<syncfusion:SfDataGrid x:Name="dataGrid"
                       GroupDropAreaText="Drag and drop the columns here"
                       ItemsSource="{Binding Orders}"
                       ShowGroupDropArea="True" />

WPF DataGrid with Custom Group Drop Area Text

GroupDropArea height and appearance

SfDataGrid allows you to customize the appearance and height of GroupDropArea by writing the style of TargetType GroupDropArea.

<Window.Resources>
    <Style TargetType="syncfusion:GroupDropArea">
        <Setter Property="Height" Value="80" />        
        <Setter Property="Foreground" Value="Red" />
        <Setter Property="Background" Value="Pink" />
    </Style>
</Window.Resources>

Customizing GroupDropDrea Height in WPF DataGrid

Expanding GroupDropArea while loading

By default, the GroupDropArea will be expanded while dragging the column towards the GroupDropArea. You can set the GroupDropArea to be always expanded by setting the SfDataGrid.IsGroupDropAreaExpanded property to true.

<syncfusion:SfDataGrid  x:Name="dataGrid"
                        AutoGenerateColumns="True"
                        IsGroupDropAreaExpanded="True"
                        ItemsSource="{Binding Orders}"
                        ShowGroupDropArea="True" />
this.dataGrid.IsGroupDropAreaExpanded = true;

Custom grouping

DataGrid allows you to group the data based on custom logic when the built-in grouping functionality doesn’t meet your requirement.

To perform custom grouping on a particular column , specify the custom logic through GroupColumnDescription.Converter property and the column name to GroupColumnDescription.ColumnName property.

For an example, the Date column is grouped based on the week basis in the following example.

public class GroupDateTimeConverter : IValueConverter
{
    public object Convert(object value, System.Type targetType, object parameter, CultureInfo culture)
    {
        var saleinfo = value as SalesByDate;
        var dt = DateTime.Now;
        var days = (int)Math.Floor((dt - saleinfo.Date).TotalDays);
        var dayofweek = (int)dt.DayOfWeek;
        var difference = days - dayofweek;

        if (days <= dayofweek)
        {

            if (days == 0)
                return "TODAY";

            if (days == 1)
                return "YESTERDAY";
            return saleinfo.Date.DayOfWeek.ToString().ToUpper();
        }

        if (difference > 0 && difference <= 7)
            return "LAST WEEK";

        if (difference > 7 && difference <= 14)
            return "TWO WEEKS AGO";

        if (difference > 14 && difference <= 21)
            return "THREE WEEKS AGO";

        if (dt.Year == saleinfo.Date.Year && dt.Month == saleinfo.Date.Month)
            return "EARLIER THIS MONTH";

        if (DateTime.Now.AddMonths(-1).Month == saleinfo.Date.Month)
            return "LAST MONTH";
        return "OLDER";
    }

    public object ConvertBack(object value, System.Type targetType, object parameter, CultureInfo culture)
    {
        throw new System.NotImplementedException();
    }
}

Now , assign the GroupDateTimeConverter into GroupColumnDescription.Converter and set Date property to GroupColumnDescription.ColumnName property.

<Window.Resources>
    <local:GroupDateTimeConverter x:Key="customGroupDateTimeConverter" />        
</Window.Resources>
  
<syncfusion:SfDataGrid  x:Name="dataGrid"                          
                        AutoGenerateColumns="True"                          
                        ItemsSource="{Binding DailySalesDetails}">

    <syncfusion:SfDataGrid.GroupColumnDescriptions>
        <syncfusion:GroupColumnDescription ColumnName="Date" Converter="{StaticResource customGroupDateTimeConverter}" />
    </syncfusion:SfDataGrid.GroupColumnDescriptions>
        
</syncfusion:SfDataGrid>

WPF DataGrid with Custom Grouping

You can download samples from below location,
Refer sample for Custom grouping when ItemsSource is ObservableCollection.

Refer sample for Custom grouping when ItemsSource is DataTable.

You can refer here to apply custom sorting when grouping is applied.

Sorting the grouped column records

In custom grouping, you can sort all the inner records of each group by setting GroupColumnDescription.SortGroupRecords
sorted based on the column name described in GroupColumnDescription.

<syncfusion:SfDataGrid.GroupColumnDescriptions>
    <syncfusion:GroupColumnDescription ColumnName="SickLeaveHours"
                                       Converter="{StaticResource customGrouping}"
                                       SortGroupRecords="True" />
</syncfusion:SfDataGrid.GroupColumnDescriptions>
GroupColumnDescription groupColumnDesc = new GroupColumnDescription()
{
    ColumnName = "SickLeaveHours",
    Converter = new CustomGroupingConverter(),
    SortGroupRecords = true
};
dataGrid.GroupColumnDescriptions.Add(groupColumnDesc);

In the below screenshot custom grouping is applied based on SickLeaveHours column and the inner records in each group are sorted based on SickLeaveHours value.

Sorting Inner Records Group in WPF DataGrid

Sorting groups based on summary values

DataGrid allows you to sort the groups based its summary values. You can sort the groups based on summary aggregate value by using SfDataGrid. SummaryGroupComparer property.

Follow the below steps to sort the groups based on caption aggregate value.

Define custom group comparer with custom sort logic

In the below code snippet, the OrderID column compared and sorted based on the number of order count in each OrderID.

public class SortGroupComparers : IComparer<Group>, ISortDirection
{
    public ListSortDirection SortDirection { get; set; }

    public int Compare(Group x, Group y)
    {

        int cmp = 0;
        var xgroupSummary = Convert.ToInt32((x as Group).GetSummaryValue(x.SummaryDetails.SummaryRow.SummaryColumns[0].MappingName, "Count"));
        var ygroupSummary = Convert.ToInt32((y as Group).GetSummaryValue(x.SummaryDetails.SummaryRow.SummaryColumns[0].MappingName, "Count"));
        cmp = ((IComparable)xgroupSummary).CompareTo(ygroupSummary);

        if (this.SortDirection == ListSortDirection.Descending)
            cmp = -cmp;
        return cmp;
    }
}

Defining custom group comparer to DataGrid

Custom group comparer can be defined in SfDataGrid using SfDataGrid.SummaryGroupComparer property. SummaryGroupComparer maintains the custom comparers and the custom comparer gets called when corresponding column is grouped.

<syncfusion:SfDataGrid  x:Name="dataGrid"
                        AllowSorting="True"
                        AutoGenerateColumns="True"
                        ItemsSource="{Binding Orders}"
                        ShowGroupDropArea="True"
                        SummaryGroupComparer="{StaticResource groupComparer}">

    <syncfusion:SfDataGrid.GroupColumnDescriptions>
        <syncfusion:GroupColumnDescription ColumnName="OrderID" />
    </syncfusion:SfDataGrid.GroupColumnDescriptions>

    <syncfusion:SfDataGrid.CaptionSummaryRow>
        <syncfusion:GridSummaryRow Title="Items Count: {IDCount}" ShowSummaryInRow="True">
            <syncfusion:GridSummaryRow.SummaryColumns>
                <syncfusion:GridSummaryColumn Name="IDCount"
                                                Format="'{Count}'"
                                                MappingName="OrderID"
                                                SummaryType="CountAggregate" />
            </syncfusion:GridSummaryRow.SummaryColumns>
        </syncfusion:GridSummaryRow>
    </syncfusion:SfDataGrid.CaptionSummaryRow>
</syncfusion:SfDataGrid>

Displaying Grouping in WPF DataGrid using Custom Group Comparer

You can download the sample demo here.

Grouping events

GroupExpanding event

The SfDataGrid.GroupExpanding event occurs when the group is being expanded.

The GroupChangingEventArgs of the GroupExpanding event provides the information about the expanding group and it has the following members.

Group - Gets the group that’s being expanded.

Cancel – Decides whether to cancel the group expansion.

You can cancel the group expansion by setting GroupChangingEventArgs.Cancel to true.

this.dataGrid.GroupExpanding += dataGrid_GroupExpanding;

void dataGrid_GroupExpanding(object sender, Syncfusion.UI.Xaml.Grid.GroupChangingEventArgs e)
{

    if (e.Group.Key.Equals(1001))    
        e.Cancel = true;    
}

GroupExpanded event

The SfDataGrid.GroupExpanded event occurs after the group is expanded.

The GroupChangedEventArgs of the GroupExpanded event provides the information about the expanded group and it has the following member.

Group - Gets the expanded group.

GroupCollapsing event

The SfDataGrid.GroupCollapsing event occurs when the group is being collapsed.

The GroupChangingEventArgs of the GroupCollapsing event provides the information about the collapsing group and it contains the following member.

Group - Gets the group that’s being collapsed.

Cancel – Decides whether to cancel the group collapsing.

You can cancel the group is being collapsed by using GroupChangingEventArgs.Cancel of GroupCollapsing event.

this.dataGrid.GroupCollapsing += dataGrid_GroupCollapsing;

void dataGrid_GroupCollapsing(object sender, GroupChangingEventArgs e)
{

    if (e.Group.Key.Equals(1001))    
        e.Cancel = true;    
}

GroupCollapsed event

The SfDataGrid.GroupCollapsed event occurs after the group is collapsed.

GroupChangedEventArgs of the GroupCollapsed event provides the information about collapsed group and it contains the following member.

Group - Gets the collapsed group.

See Also

How to remove the gridline of WPF DataGrid (SfDataGrid) with grouping?

How to maintain expanded state of groups in printing?

How to show vertical border to the column wise summary rows?

How to define summary rows using AttachedProperty in datagrid

How to displaying Group header name based on other column

How to clear selection while grouping/ungrouping?

How to add selection to data rows of each group on expanding its CaptionSummaryRow?

How to change the CaptionSummaryRow Style based on the grouping level?

How to Change the GroupCaptionText based on Display member of the GridComboboxColumn?

How to add controls like TextBox in GroupDropArea?

How to customize the CaptionSummaryCell text in the SfDataGrid?

How to apply the Custom Grouping while grouping the column using GroupDropArea?

How to avoid selection while grouping and ungrouping in SfDataGrid?

How to customize the GroupDropArea?