Skip to main content
A newer version of this page is available. .

Working with Groups in Code

  • 9 minutes to read

Group and Ungroup Data


Groups data against this column. If data is already grouped by other columns, this column will be added to the end of the grouping queue.


Removes data grouping by this column.


Removes all data grouping.


Accepts non-negative integer values that specify the column order according to which data is grouped. Values must be unique, which means you cannot apply merged column grouping by setting column group indexes.


A collection that stores specific ColumnSortInfo objects on every grid column involved in sorting and grouping. To apply complex grouping in code, modify this collection manually by calling the GridColumnSortInfoCollection.ClearAndAddRange method. The code below applies two grouping layers: merged grouping by “Ship Country”, “Ship City” and “Ship Region” columns, followed by tier two grouping by the “Customer ID” column.

gridView1.SortInfo.ClearAndAddRange(new[] {
    new GridMergedColumnSortInfo(
        new[] {
            colShipCountry, colShipCity, colShipRegion},
        new[] {
            ColumnSortOrder.Ascending, ColumnSortOrder.Descending, ColumnSortOrder.Ascending }),
    new GridColumnSortInfo(colCustomerID, ColumnSortOrder.Descending)
}, 4);

ColumnView.StartGrouping, ColumnView.EndGrouping

Non-cancelable events that fire whenever a grouping operation takes place.

Modify Group Row Content

GridView.GroupFormat, GridColumn.GroupFormat

Allows you to modify group row content for individual Grid columns, or all columns at once.


Allows you to modify specific group row captions.

colShipCountry.GroupInterval = DevExpress.XtraGrid.ColumnGroupInterval.Alphabetical;

private void gridView1_CustomDrawGroupRow(object sender, DevExpress.XtraGrid.Views.Base.RowObjectCustomDrawEventArgs e) {
    GridGroupRowInfo info = e.Info as GridGroupRowInfo;
    if (info.Column == colShipCountry) {
        info.GroupText = "Ship country starts with " + info.GroupValueText;


Allows you to display group summaries within group rows.


Custom Grouping


Set this property to Custom to implement custom grouping.


Fires for all columns with the custom sort mode when grid data is grouped against these columns. Allows you to implement custom grouping algorithms.

ColumnView.CustomColumnDisplayText or GridView.CustomDrawGroupRow

Handle any of these events to modify group row captions accordingly to your custom grouping algorithms. The sample below illustrates how to break order dates into four seasons and group orders by these seasons.

Grid - Custom Grouping

using System;
using DevExpress.XtraGrid.Views.Grid;
using DevExpress.XtraGrid.Views.Base;
using DevExpress.XtraGrid.Views.Grid.ViewInfo;
using System.Collections.Generic;
using DevExpress.XtraGrid.Columns;

namespace CustomGroupingSample {
    public partial class XtraForm1 : DevExpress.XtraEditors.XtraForm {
        public XtraForm1() {
            // This line of code is generated by Data Source Configuration Wizard
            gridView1.OptionsView.ShowGroupedColumns = true;
            gridView1.SortInfo.ClearAndAddRange(new[] {
                new GridColumnSortInfo(colOrderDate, DevExpress.Data.ColumnSortOrder.Ascending)

            colOrderDate.SortMode = DevExpress.XtraGrid.ColumnSortMode.Custom;
            gridView1.CustomColumnGroup += GridView1_CustomColumnGroup;
            gridView1.CustomColumnDisplayText += GridView1_CustomColumnDisplayText;
            gridView1.CustomDrawGroupRow += GridView1_CustomDrawGroupRow;

        //Custom Grouping
        private void GridView1_CustomColumnGroup(object sender, CustomColumnSortEventArgs e) {
            if (e.Column == colOrderDate) {
                DateTime value1 = (DateTime)e.Value1;
                DateTime value2 = (DateTime)e.Value2;
                if (GetSeason(value1) == GetSeason(value2)) e.Result = 0;
                else e.Result = 1;
                e.Handled = true;

        //Get season by date
        private string GetSeason(DateTime date) {
            Int32 month = date.Month;
            string season = "Winter";
            if (month == 3 || month == 4 || month == 5) season = "Spring";
            if (month == 6 || month == 7 || month == 8) season = "Summer";
            if (month == 9 || month == 10 || month == 11) season = "Fall";
            return season;

        //Custom group row content  (option #1)
        private void GridView1_CustomColumnDisplayText(object sender, CustomColumnDisplayTextEventArgs e) {
            GridView view = sender as GridView;
            if (view == null) return;
            if (e.Column == colOrderDate && e.IsForGroupRow) {
                DateTime rowValue = (DateTime)view.GetGroupRowValue(e.GroupRowHandle, e.Column);
                string season = GetSeason(rowValue);
                if (season != "Winter") e.DisplayText = season + " " + rowValue.Year;
                else e.DisplayText = season + " " + rowValue.Year + "/" + rowValue.AddYears(1).Year;

        //Custom group row content  (option #2)
        private void GridView1_CustomDrawGroupRow(object sender, DevExpress.XtraGrid.Views.Base.RowObjectCustomDrawEventArgs e) {
            GridGroupRowInfo info = e.Info as GridGroupRowInfo;
            GridView view = sender as GridView;
            if (info.Column == colOrderDate) {
                DateTime rowValue = (DateTime)view.GetGroupRowValue(info.RowHandle, info.Column);
                string season = GetSeason(rowValue);
                if (season != "Winter") info.GroupText = "Order Date: " + season + " " + rowValue.Year;
                else info.GroupText = "Order Date: " + season + " " + rowValue.Year + "/" + rowValue.AddYears(1).Year;

Locate and Process Group Rows

Row Handles

Row handles are integer values that identify both data (positive values) and group (negative values) rows.

Grid - Group Row Handles


Identifies the nesting level of a row.

Grid - Row Levels


Returns the number of immediate child rows for a group row.


Returns the row handle of a group row’s child data row. The following example shows how to change the “Price” column value for all the data rows belonging to the focused data group. Prices change when end-users press the “Discount” button.

using DevExpress.XtraGrid.Views.Grid;
private void buttonDiscount_Click(object sender, System.EventArgs e) {
    GridView view = gridView1;
    int rowHandle = view.FocusedRowHandle;
    ArrayList rowsToDiscount = new ArrayList();
    //Get related data rows 
        getChildRows(view, rowHandle, rowsToDiscount);
    //Change the values of the rows 

//Returns the child data rows for the given group row 
public void getChildRows(GridView view, int groupRowHandle, ArrayList childRows) {
    if(!view.IsGroupRow(groupRowHandle)) return;
    //Get the number of immediate children 
    int childCount = view.GetChildRowCount(groupRowHandle);
    for(int i=0; i<childCount; i++){
        //Get the handle of a child row with the required index 
        int childHandle = view.GetChildRowHandle(groupRowHandle, i);
        //If the child is a group row, then add its children to the list 
            getChildRows(view, childHandle, childRows);
        else {                    
            // The child is a data row.  
            // Add it to the childRows as long as the row wasn't added before 
            object row = view.GetRow(childHandle);

//Changes the values of the Price column for the specified rows 
public void discount(ArrayList rows) {
    for(int i = 0; i < rows.Count; i++) {
        DataRow row = (rows[i] as DataRowView).Row;    
        decimal oldValue = (decimal)row["Price"];
        row["Price"] = oldValue * 0.95m;               


Returns the row handle of a parent row.


Methods that retrieve System.Data.DataRowView or other objects, which represent data source rows.

Expand and Collapse Rows


Returns whether or not the row is expanded.


Call this method to expand or collapse a row.


Expands or collapses a row itself and (optionally) all of its child rows.


Cancelable events that fire when a group is to be expanded or collapsed.


These events occur after a row has been expanded or collapsed.


Scrolls the View to display the required row and selects this row. Expands the row’s parent group.


Scrolls the View to display the required row. If the row belongs to a group, this group expands. The code snippet below displays all rows whose “InStock” column values equal false.

using DevExpress.XtraGrid.Views.Grid;
GridView View = gridView1;
int rowHandle = -1;
do {
    rowHandle = View.LocateByValue(rowHandle+1, View.Columns["Is In Stock"], false);
    View.MakeRowVisible(rowHandle, false);
} while(rowHandle != GridControl.InvalidRowHandle);
See Also