Back to Devexpress

Working with Total, Group, and Custom Summaries in Code

windowsforms-701-controls-and-libraries-data-grid-summaries-working-with-summaries-in-code-custom-summaries.md

latest24.2 KB
Original Source

Working with Total, Group, and Custom Summaries in Code

  • May 01, 2025
  • 10 minutes to read

Create Total Summaries

The following example creates total summaries (Count, Average, Custom) and displays them in the grid’s footer. The example handles the GridView.CustomSummaryCalculate event to count the number of orders created within the current week.

Run Demo: Total Summary

csharp
using System;
using DevExpress.Data;
using DevExpress.XtraBars.Ribbon;
using DevExpress.XtraGrid;
using DevExpress.XtraGrid.Views.Grid;

namespace GridSummaries
{
    public partial class Form1 : RibbonForm
    {
        public Form1()
        {
            InitializeComponent();
        }
        private void Form1_Load(object sender, EventArgs e)
        {
            // Load data into the 'nwindDataSet.Orders' table.
            this.ordersTableAdapter.Fill(this.nwindDataSet.Orders);
            // Create summaries
            CreateTotalSummaries();
            // Handle the event to calculate a custom summary
            gridView.CustomSummaryCalculate += GridView_CustomSummaryCalculate;
            // Display a footer with summaries
            gridView.OptionsView.ShowFooter = true;
        }

        void CreateTotalSummaries()
        {
            GridColumnSummaryItem total = new GridColumnSummaryItem()
            {
                SummaryType = SummaryItemType.Count,
                DisplayFormat = "{0} orders"
            };
            // Add the total summary to the 'OrderID' column
            colOrderID.Summary.Add(total);

            GridColumnSummaryItem average = new GridColumnSummaryItem()
            {
                SummaryType = SummaryItemType.Average,
                FieldName = "Freight",
                DisplayFormat = "Average: {0:#.#}"
            };
            // Add the average summary to the 'Freight' column
            colFreight.Summary.Add(average);

            GridColumnSummaryItem custom = new GridColumnSummaryItem()
            {
                SummaryType = SummaryItemType.Custom,
                FieldName = "OrderDate",
                DisplayFormat = "This week: {0:n0} orders"
            };
            // Add the custom summary to the 'OrderDate' column
            colOrderDate.Summary.Add(custom);
        }

        int orderCount = 0;
        private void GridView_CustomSummaryCalculate(object sender, CustomSummaryEventArgs e)
        {
            GridView view = sender as GridView;
            if (e.IsTotalSummary)
            {
                switch (e.SummaryProcess)
                {
                    // Start calculation
                    case CustomSummaryProcess.Start:
                        orderCount = 0;
                        break;
                    // Consequent calculations
                    case CustomSummaryProcess.Calculate:
                        DateTime today = DateTime.Today;
                        DateTime orderDate = Convert.ToDateTime(view.GetRowCellValue(e.RowHandle, view.Columns["OrderDate"]));
                        int currentDayOfWeek = (int)today.DayOfWeek;
                        DateTime startOfWeek = today.AddDays(-currentDayOfWeek + (currentDayOfWeek == 0 ? -6 : 1)); // Start on Monday
                        DateTime endOfWeek = startOfWeek.AddDays(6); // End on Sunday

                        if (orderDate.Date >= startOfWeek && orderDate <= endOfWeek)
                            orderCount++;
                        break;
                    // Final summary value
                    case CustomSummaryProcess.Finalize:
                        e.TotalValue = orderCount;
                        break;
                }
            }
        }
    }
}
vb
Imports System
Imports DevExpress.Data
Imports DevExpress.XtraBars.Ribbon
Imports DevExpress.XtraGrid
Imports DevExpress.XtraGrid.Views.Grid

Namespace GridSummaries
    Partial Public Class Form1
        Inherits RibbonForm

        Public Sub New()
            InitializeComponent()
        End Sub
        Private Sub Form1_Load(ByVal sender As Object, ByVal e As EventArgs)
            ' Load data into the 'nwindDataSet.Orders' table.
            Me.ordersTableAdapter.Fill(Me.nwindDataSet.Orders)
            ' Create summaries
            CreateTotalSummaries()
            ' Handle the event to calculate a custom summary
            AddHandler gridView.CustomSummaryCalculate, AddressOf GridView_CustomSummaryCalculate
            ' Display a footer with summaries
            gridView.OptionsView.ShowFooter = True
        End Sub

        Private orderCount As Integer = 0
        Private Sub GridView_CustomSummaryCalculate(ByVal sender As Object, ByVal e As CustomSummaryEventArgs)
            Dim view As GridView = TryCast(sender, GridView)
            If e.IsTotalSummary Then
                Select Case e.SummaryProcess
                    ' Start calculation
                    Case CustomSummaryProcess.Start
                        orderCount = 0
                    ' Consequent calculations
                    Case CustomSummaryProcess.Calculate
                        Dim today As Date = Date.Today
                        Dim orderDate As Date = Convert.ToDateTime(view.GetRowCellValue(e.RowHandle, view.Columns("OrderDate")))
                        Dim currentDayOfWeek As Integer = CInt(today.DayOfWeek)
                        Dim startOfWeek As Date = today.AddDays(-currentDayOfWeek + (If(currentDayOfWeek = 0, -6, 1))) ' Start on Monday
                        Dim endOfWeek As Date = startOfWeek.AddDays(6) ' End on Sunday

                        If orderDate.Date >= startOfWeek AndAlso orderDate <= endOfWeek Then
                            orderCount += 1
                        End If
                    ' Final summary value
                    Case CustomSummaryProcess.Finalize
                        e.TotalValue = orderCount
                End Select
            End If
        End Sub
        Private Sub CreateTotalSummaries()
            Dim total As New GridColumnSummaryItem() With {
                .SummaryType = SummaryItemType.Count,
                .DisplayFormat = "{0} orders"
            }
            ' Add the total summary to the 'OrderID' column
            colOrderID.Summary.Add(total)

            Dim average As New GridColumnSummaryItem() With {
                .SummaryType = SummaryItemType.Average,
                .FieldName = "Freight",
                .DisplayFormat = "Average: {0:#.#}"
            }
            ' Add the average summary to the 'Freight' column
            colFreight.Summary.Add(average)

            Dim custom As New GridColumnSummaryItem() With {
                .SummaryType = SummaryItemType.Custom,
                .FieldName = "OrderDate",
                .DisplayFormat = "This week: {0:n0} orders"
            }
            ' Add the custom summary to the 'OrderDate' column
            colOrderDate.Summary.Add(custom)
        End Sub
    End Class
End Namespace

Create Group Summaries

The following example creates group summary items (Count, Average, Custom). The ‘Count’ summary is displayed in group rows. ‘Average’ and ‘Custom’ summaries are displayed in group footers. To create a group summary, create a GridGroupSummaryItem object, customize its settings, and add the object to the GridView.GroupSummary collection.

csharp
using System;
using DevExpress.Data;
using DevExpress.XtraBars.Ribbon;
using DevExpress.XtraGrid;
using DevExpress.XtraGrid.Views.Grid;

namespace GridSummaries
{
    public partial class Form1 : RibbonForm
    {
        public Form1()
        {
            InitializeComponent();
        }
        private void Form1_Load(object sender, EventArgs e)
        {
            // Load data into the 'nwindDataSet.Orders' table
            this.ordersTableAdapter.Fill(this.nwindDataSet.Orders);
            // Create summaries
            CreateGroupSummaries();
            // Handle the event to calculate a custom summary
            gridView.CustomSummaryCalculate += GridView_CustomSummaryCalculate;
            // Display a group footer within expanded groups
            gridView.OptionsView.GroupFooterShowMode = GroupFooterShowMode.VisibleIfExpanded;
            // Group the View by the 'ShipCountry' column
            colShipCountry.GroupIndex = 0;
            // Expand the first group
            gridView.ExpandGroupRow(-1);
        }
        void CreateGroupSummaries()
        {
            GridGroupSummaryItem total = new GridGroupSummaryItem()
            {
                SummaryType = SummaryItemType.Count,
                DisplayFormat = "{0} orders"
            };

            GridGroupSummaryItem average = new GridGroupSummaryItem()
            {
                SummaryType = SummaryItemType.Average,
                FieldName = "Freight",
                DisplayFormat = "Average: {0:#.#}",
                ShowInGroupColumnFooter = colFreight
            };

            GridGroupSummaryItem custom = new GridGroupSummaryItem()
            {
                SummaryType = SummaryItemType.Custom,
                FieldName = "OrderDate",
                DisplayFormat = "This week: {0:n0} orders",
                ShowInGroupColumnFooter = colOrderDate
            };

            // Add group summary items to the 'GroupSummary' collection
            gridView.GroupSummary.AddRange(new GridSummaryItem[]{
                total, average, custom
            });
        }

        int orderCount = 0;
        private void GridView_CustomSummaryCalculate(object sender, CustomSummaryEventArgs e)
        {
            GridView view = sender as GridView;
            if (e.IsGroupSummary)
            {
                switch (e.SummaryProcess)
                {
                    // Start calculation
                    case CustomSummaryProcess.Start:
                        orderCount = 0;
                        break;
                    // Consequent calculations
                    case CustomSummaryProcess.Calculate:
                        DateTime today = DateTime.Today;
                        DateTime orderDate = Convert.ToDateTime(view.GetRowCellValue(e.RowHandle, view.Columns["OrderDate"]));
                        int currentDayOfWeek = (int)today.DayOfWeek;
                        DateTime startOfWeek = today.AddDays(-currentDayOfWeek + (currentDayOfWeek == 0 ? -6 : 1)); // Start on Monday
                        DateTime endOfWeek = startOfWeek.AddDays(6); // End on Sunday

                        if (orderDate.Date >= startOfWeek && orderDate <= endOfWeek)
                            orderCount++;
                        break;
                    // Final summary value
                    case CustomSummaryProcess.Finalize:
                        e.TotalValue = orderCount;
                        break;
                }
            }
        }
    }
}
vb
Imports System
Imports DevExpress.Data
Imports DevExpress.XtraBars.Ribbon
Imports DevExpress.XtraGrid
Imports DevExpress.XtraGrid.Views.Grid

Namespace GridSummaries
    Partial Public Class Form1
        Inherits RibbonForm

        Public Sub New()
            InitializeComponent()
        End Sub
        Private Sub Form1_Load(ByVal sender As Object, ByVal e As EventArgs)
            ' Load data into the 'nwindDataSet.Orders' table
            Me.ordersTableAdapter.Fill(Me.nwindDataSet.Orders)
            ' Create summaries
            CreateGroupSummaries()
            ' Handle the event to calculate a custom summary
            AddHandler gridView.CustomSummaryCalculate, AddressOf GridView_CustomSummaryCalculate
            ' Display a group footer within expanded groups
            gridView.OptionsView.GroupFooterShowMode = GroupFooterShowMode.VisibleIfExpanded
            ' Group the View by the 'ShipCountry' column
            colShipCountry.GroupIndex = 0
            ' Expand the first group
            gridView.ExpandGroupRow(-1)
        End Sub
        Private Sub CreateGroupSummaries()
            Dim total As New GridGroupSummaryItem() With {
                .SummaryType = SummaryItemType.Count,
                .DisplayFormat = "{0} orders"
            }

            Dim average As New GridGroupSummaryItem() With {
                .SummaryType = SummaryItemType.Average,
                .FieldName = "Freight",
                .DisplayFormat = "Average: {0:#.#}",
                .ShowInGroupColumnFooter = colFreight
            }

            Dim custom As New GridGroupSummaryItem() With {
                .SummaryType = SummaryItemType.Custom,
                .FieldName = "OrderDate",
                .DisplayFormat = "This week: {0:n0} orders",
                .ShowInGroupColumnFooter = colOrderDate
            }

            ' Add group summary items to the 'GroupSummary' collection
            gridView.GroupSummary.AddRange(New GridSummaryItem(){ total, average, custom })
        End Sub

        Private orderCount As Integer = 0
        Private Sub GridView_CustomSummaryCalculate(ByVal sender As Object, ByVal e As CustomSummaryEventArgs)
            Dim view As GridView = TryCast(sender, GridView)
            If e.IsGroupSummary Then
                Select Case e.SummaryProcess
                    ' Start calculation
                    Case CustomSummaryProcess.Start
                        orderCount = 0
                    ' Consequent calculations
                    Case CustomSummaryProcess.Calculate
                        Dim today As Date = Date.Today
                        Dim orderDate As Date = Convert.ToDateTime(view.GetRowCellValue(e.RowHandle, view.Columns("OrderDate")))
                        Dim currentDayOfWeek As Integer = CInt(today.DayOfWeek)
                        Dim startOfWeek As Date = today.AddDays(-currentDayOfWeek + (If(currentDayOfWeek = 0, -6, 1))) ' Start on Monday
                        Dim endOfWeek As Date = startOfWeek.AddDays(6) ' End on Sunday

                        If orderDate.Date >= startOfWeek AndAlso orderDate <= endOfWeek Then
                            orderCount += 1
                        End If
                    ' Final summary value
                    Case CustomSummaryProcess.Finalize
                        e.TotalValue = orderCount
                End Select
            End If
        End Sub
    End Class
End Namespace

Obtain Summary Values

Use the following API to obtain summaries, aggregated values (summary values), and formatted summary text displayed in footer cells.

Note

In master detail mode, when a master row is expanded, the Data Grid creates a Pattern View to display detail data. Pattern Views only store settings and are never connected to data. To access summaries in detail views, use columns and summaries of clone Views.

Refer to the following help topic for additional information: Master-Detail Relationships.

Common API

API MemberDescription
GridSummaryItem.SummaryValueGets the value of the summary item.
GridSummaryItem.GetDisplayTextReturns the formatted summary value as a string.
csharp
using DevExpress.XtraGrid;

...
// Create a total summary that calculates the total number of employees 
GridColumnSummaryItem summary = new GridColumnSummaryItem(DevExpress.Data.SummaryItemType.Count, "EmployeeID", "{0} Employees") { Tag = "Employees" };
gridView.Columns["EmployeeID"].Summary.Add(summary);
// Display a footer with total summaries
gridView.OptionsView.ShowFooter = true;
...

// Obtain a total summary value
object count = colEmployeeID.Summary["Employees"].SummaryValue;

Total Summaries

|

API Member

|

Description

| | --- | --- | |

GridColumn.SummaryText

|

Returns the text displayed by total summaries owned by this column.

The return value is a string that delimits values of separate summaries with the \r\n sequence (for example, “Max: 1007.6400\r\n830 records”).

|

Group Summaries

|

API Member

|

Description

| | --- | --- | |

GridView.GetRowSummaryItem

|

Takes a row handle and a column as parameters and returns a DictionaryEntry object that allows you to obtain:

  • A summary item associated with this row and column, accessed through the DictionaryEntry.Key property.
  • A summary item’s value, accessed through the DictionaryEntry.Value property.

| |

GridView.GetGroupSummaryValue

GridView.GetGroupSummaryDisplayText

|

Return the value and display text of the specified group summary item displayed in the specified group row.

| |

GridView.GetGroupSummaryValues

|

Returns a hashtable that stores summary items (keys) and their values for the specified group row. The hashtable contains entries for summary items displayed in both group footers and group rows.

| |

GridView.GetGroupSummaryText

|

Returns the group summary item’s text displayed in the specified group row.

| |

GridView.GetRowFooterCellText

|

Returns the group summary item’s text displayed in the specified group footer cell.

|

Example: Obtain Summary Values

The following code snippet does the following:

  • Highlights group rows that contain more than 30 rows.
  • Highlights the total summary in the “Freight” column if the total summary value is greater than 40.

csharp
using System.Drawing;
using DevExpress.XtraGrid;
using DevExpress.XtraGrid.Views.Grid;

// Highlight a total summary
private void GridView_CustomDrawFooterCell(object sender, FooterCellCustomDrawEventArgs e)
{
    if(e.Column == colFreight) {
        GridSummaryItem summary = e.Info.SummaryItem;
        double summaryValue = Convert.ToDouble(summary.SummaryValue);
        if (summaryValue > 40)
            e.Appearance.ForeColor = Color.Red;
    }
}

// Highlight group rows based on a condition
private void GridView_RowStyle(object sender, RowStyleEventArgs e)
{
    GridView view = sender as GridView;
    if (view == null) return;
    if (e.RowHandle >= 0 || view.GroupCount == 0) return;
    // Get all group summary values
    Hashtable ht = view.GetGroupSummaryValues(e.RowHandle);
    // Obtain the first group summary
    GridSummaryItem groupSummaryItem = view.GroupSummary[0];
    // Obtain the group summary's value 
    int childRecordCount = Convert.ToInt32(ht[groupSummaryItem]);
    if (childRecordCount > 30)
        e.Appearance.BackColor = Color.FromArgb(70, Color.Yellow);
}
vb
Imports System.Drawing
Imports DevExpress.XtraGrid
Imports DevExpress.XtraGrid.Views.Grid

' Highlight a total summary
Private Sub GridView_CustomDrawFooterCell(ByVal sender As Object, ByVal e As FooterCellCustomDrawEventArgs)
    If e.Column = colFreight Then
        Dim summary As GridSummaryItem = e.Info.SummaryItem
        Dim summaryValue As Double = Convert.ToDouble(summary.SummaryValue)
        If summaryValue > 40 Then
            e.Appearance.ForeColor = Color.Red
        End If
    End If
End Sub

' Highlight group rows based on a condition
Private Sub GridView_RowStyle(ByVal sender As Object, ByVal e As RowStyleEventArgs)
    Dim view As GridView = TryCast(sender, GridView)
    If view Is Nothing Then
        Return
    End If
    If e.RowHandle >= 0 OrElse view.GroupCount = 0 Then
        Return
    End If
    ' Get all group summary values
    Dim ht As Hashtable = view.GetGroupSummaryValues(e.RowHandle)
    ' Obtain the first group summary. 
    Dim groupSummaryItem As GridSummaryItem = view.GroupSummary(0)
    ' Obtain the group summary's value
    Dim childRecordCount As Integer = Convert.ToInt32(ht(groupSummaryItem))
    If childRecordCount > 30 Then
        e.Appearance.BackColor = Color.FromArgb(70, Color.Yellow)
    End If
End Sub

This example customizes the grid’s footer menu and calculates custom total summaries.

View Example

Update Summaries

The WinForms Data Grid updates summaries when a user focuses a row or presses the End Init Data Navigator button. You can disable this automatic update for total summaries to improve overall grid performance with large data sources. To do this, disable the View’s OptionsBehavior.AutoUpdateTotalSummary option.

Use one of the following methods to forcibly update summaries when needed:

The following code snippet updates total summaries after the user changes a value in the “Quantity” column:

csharp
gridView1.CellValueChanged += GridView1_CellValueChanged;

private void GridView1_CellValueChanged(object sender, DevExpress.XtraGrid.Views.Base.CellValueChangedEventArgs e)
{
    GridView view = sender as GridView;
    if (e.Column == colQuantity)
    {
        view.UpdateTotalSummary();
    }
}
vb
Private gridView1.CellValueChanged += AddressOf GridView1_CellValueChanged

Private Sub GridView1_CellValueChanged(ByVal sender As Object, ByVal e As DevExpress.XtraGrid.Views.Base.CellValueChangedEventArgs)
    Dim view As GridView = TryCast(sender, GridView)
    If e.Column = colQuantity Then
        view.UpdateTotalSummary()
    End If
End Sub

See Also

Summaries

Tutorial: Total Summaries

Tutorial: Group Summaries

Tutorial: Custom Summary Functions