This example demonstrates how to add three total summaries with different types and aggregate functions.

Open the Manual total summary live demo and remove its code from the "ExampleCode" tab. Create three GridSummaryItem objects:
- a summary item for displaying total record count - does not require setting the GridSummaryItem.FieldName property;
- a summary item for calculating an average length - utilizes a custom {0:#.#} display format;
- a summary item with a custom aggregate function.
C# |
GridColumnSummaryItem siTotal = new GridColumnSummaryItem();
siTotal.SummaryType = SummaryItemType.Count;
siTotal.DisplayFormat = "{0} records";
GridColumnSummaryItem siAverage = new GridColumnSummaryItem();
siAverage.SummaryType = SummaryItemType.Average;
siAverage.FieldName = "Length";
siAverage.DisplayFormat = "Average: {0:#.#}";
GridColumnSummaryItem siRecordDate = new GridColumnSummaryItem();
siRecordDate.SummaryType = SummaryItemType.Custom;
siRecordDate.FieldName = "RecordDate";
siRecordDate.DisplayFormat = "This week: {0:n0} records";
|
VB |
Dim siTotal As New GridColumnSummaryItem()
siTotal.SummaryType = SummaryItemType.Count
siTotal.DisplayFormat = "{0} records"
Dim siAverage As New GridColumnSummaryItem()
siAverage.SummaryType = SummaryItemType.Average
siAverage.FieldName = "Length"
siAverage.DisplayFormat = "Average: {0:#.#}"
Dim siRecordDate As New GridColumnSummaryItem()
siRecordDate.SummaryType = SummaryItemType.Custom
siRecordDate.FieldName = "RecordDate"
siRecordDate.DisplayFormat = "This week: {0:n0} records"
|
For the third summary item, you need to provide a custom aggregate function that calculates the summary value. To do so, handle the GridView.CustomSummaryCalculate event. The code sample below determines if the processed order belongs to the current week, and if so, increments the summary.
C# |
int dateCount = 0;
gridView.CustomSummaryCalculate += (sender, e) => {
if (e.IsTotalSummary) {
GridView view = sender as GridView;
switch (e.SummaryProcess) {
case CustomSummaryProcess.Start:
dateCount = 0;
break;
case CustomSummaryProcess.Calculate:
DateTime value = Convert.ToDateTime(view.GetRowCellValue(e.RowHandle, view.Columns["RecordDate"]));
DateTime current = DateTime.Now;
System.Globalization.CultureInfo cul = System.Globalization.CultureInfo.CurrentCulture;
var valueWeek = cul.Calendar.GetWeekOfYear(
value,
System.Globalization.CalendarWeekRule.FirstDay,
DayOfWeek.Monday);
var currentWeek = cul.Calendar.GetWeekOfYear(
current,
System.Globalization.CalendarWeekRule.FirstDay,
DayOfWeek.Monday);
if (valueWeek == currentWeek) dateCount++;
break;
case CustomSummaryProcess.Finalize:
e.TotalValue = dateCount;
break;
}
}
};
|
VB |
Dim dateCount As Integer = 0
AddHandler gridView.CustomSummaryCalculate, Sub(sender, e)
If e.IsTotalSummary Then
Dim view As GridView = TryCast(sender, GridView)
Select Case e.SummaryProcess
Case CustomSummaryProcess.Start
dateCount = 0
Case CustomSummaryProcess.Calculate
Dim value As Date = Convert.ToDateTime(view.GetRowCellValue(e.RowHandle, view.Columns("RecordDate")))
Dim current As Date = Date.Now
Dim cul As System.Globalization.CultureInfo = System.Globalization.CultureInfo.CurrentCulture
Dim valueWeek = cul.Calendar.GetWeekOfYear(value, System.Globalization.CalendarWeekRule.FirstDay, DayOfWeek.Monday)
Dim currentWeek = cul.Calendar.GetWeekOfYear(current, System.Globalization.CalendarWeekRule.FirstDay, DayOfWeek.Monday)
If valueWeek = currentWeek Then
dateCount += 1
End If
Case CustomSummaryProcess.Finalize
e.TotalValue = dateCount
End Select
End If
End Sub
|
Add all three summary items to the GridColumn.SummaryItem collections of required columns and explicitly show the View footer by enabling the GridOptionsView.ShowFooter setting.
C# |
gridView.Columns["ID"].Summary.Add(siTotal);
gridView.Columns["RecordDate"].Summary.Add(siRecordDate);
gridView.Columns["Length"].Summary.Add(siAverage);
gridView.OptionsView.ShowFooter = true;
|
VB |
gridView.Columns("ID").Summary.Add(siTotal)
gridView.Columns("RecordDate").Summary.Add(siRecordDate)
gridView.Columns("Length").Summary.Add(siAverage)
gridView.OptionsView.ShowFooter = True
|
The code below creates three group summaries. You can test this sample in the Manual total summary demo.
- a "Count" summary displayed in group rows;
- an "Average" summary shown in group footer area;
- a group footer summary with a custom aggregate function.

To add group summaries in code, you need to either manually create GridGroupSummaryItem objects and place them inside the GridView.GroupSummary collection, or call the collection's Add method with required parameters.
C# |
GridGroupSummaryItem gscCount = new GridGroupSummaryItem();
gscCount.SummaryType = SummaryItemType.Count;
gscCount.DisplayFormat = "({0} records)";
gridView.GroupSummary.Add(gscCount);
gridView.GroupSummary.Add(SummaryItemType.Average, "Length", gridView.Columns["Length"], "Average: {0}");
|
VB |
Dim gscCount As New GridGroupSummaryItem()
gscCount.SummaryType = SummaryItemType.Count
gscCount.DisplayFormat = "({0} records)"
gridView.GroupSummary.Add(gscCount)
gridView.GroupSummary.Add(SummaryItemType.Average, "Length", gridView.Columns("Length"), "Average: {0}")
|
A summary with a custom aggregate function requires handling the GridView.CustomSummaryCalculate event to calculate a summary value.
C# |
int dateCount = 0;
gridView.CustomSummaryCalculate += (sender, e) => {
if (e.IsGroupSummary) {
GridView view = sender as GridView;
switch (e.SummaryProcess) {
case CustomSummaryProcess.Start:
dateCount = 0;
break;
case CustomSummaryProcess.Calculate:
DateTime value = Convert.ToDateTime(view.GetRowCellValue(e.RowHandle, view.Columns["RecordDate"]));
DateTime current = DateTime.Now;
System.Globalization.CultureInfo cul = System.Globalization.CultureInfo.CurrentCulture;
var valueWeek = cul.Calendar.GetWeekOfYear(
value,
System.Globalization.CalendarWeekRule.FirstDay,
DayOfWeek.Monday);
var currentWeek = cul.Calendar.GetWeekOfYear(
current,
System.Globalization.CalendarWeekRule.FirstDay,
DayOfWeek.Monday);
if (valueWeek == currentWeek) dateCount++;
break;
case CustomSummaryProcess.Finalize:
e.TotalValue = dateCount;
break;
}
}
};
gridView.GroupSummary.Add(SummaryItemType.Custom, "RecordDate", gridView.Columns["RecordDate"], "{0} this week");
|
VB |
Dim dateCount As Integer = 0
AddHandler gridView.CustomSummaryCalculate, Sub(sender, e)
If e.IsGroupSummary Then
Dim view As GridView = TryCast(sender, GridView)
Select Case e.SummaryProcess
Case CustomSummaryProcess.Start
dateCount = 0
Case CustomSummaryProcess.Calculate
Dim value As Date = Convert.ToDateTime(view.GetRowCellValue(e.RowHandle, view.Columns("RecordDate")))
Dim current As Date = Date.Now
Dim cul As System.Globalization.CultureInfo = System.Globalization.CultureInfo.CurrentCulture
Dim valueWeek = cul.Calendar.GetWeekOfYear(value, System.Globalization.CalendarWeekRule.FirstDay, DayOfWeek.Monday)
Dim currentWeek = cul.Calendar.GetWeekOfYear(current, System.Globalization.CalendarWeekRule.FirstDay, DayOfWeek.Monday)
If valueWeek = currentWeek Then
dateCount += 1
End If
Case CustomSummaryProcess.Finalize
e.TotalValue = dateCount
End Select
End If
End Sub
gridView.GroupSummary.Add(SummaryItemType.Custom, "RecordDate", gridView.Columns("RecordDate"), "{0} this week")
|
Utilize the following API to retrieve summaries, their values and displayed text.
Common API
GridSummaryItem.SummaryValue
Gets the value of this summary item.
GridSummaryItem.GetDisplayText
Applies the current display format rule expression to convert any value into a display text.
Total Summaries
GridColumn.SummaryText
Returns the text displayed by total summaries owned by this column. The return value is a single string that delimits values of separate summaries with the "\r\n" sequence (e.g., "Max: 1007.6400\r\n830 records").
Group Summaries
GridView.GetRowSummaryItem
Takes a row handle and a column as parameters and returns a DictionaryEntry object that provides access to:
- a summary item associated with these row and column - accessed through the DictionaryEntry.Key property;
- a summary item's value - accessed through the DictionaryEntry.Value property.
The code sample below retrieves a group summary item text whenever the focused row changes.
C# |
using DevExpress.XtraGrid.Views.Base;
private void gridView1_FocusedRowChanged(object sender, FocusedRowChangedEventArgs e) {
GridView currentView = sender as GridView;
DictionaryEntry ent = currentView.GetRowSummaryItem(e.FocusedRowHandle,
currentView.FocusedColumn);
if(ent.Key != null) {
GridGroupSummaryItem si = (GridGroupSummaryItem)ent.Key;
this.Text = si.GetDisplayText(ent.Value, true);
} else {
this.Text = "There is no summary for this row and column";
}
}
|
VB |
Imports DevExpress.XtraGrid.Views.Base
Private Sub gridView1_FocusedRowChanged(ByVal sender As Object, _
ByVal e As FocusedRowChangedEventArgs) Handles gridView1.FocusedRowChanged
Dim currentView As GridView = sender
Dim ent As DictionaryEntry = currentView.GetRowSummaryItem( _
e.FocusedRowHandle, currentView.FocusedColumn)
If Not ent.Key Is Nothing Then
Dim si As GridGroupSummaryItem = ent.Key
Me.Text = si.GetDisplayText(ent.Value, True)
Else
Me.Text = "There is no summary for this row and column"
End If
End Sub
|
GridView.GetGroupSummaryValue, GridView.GetGroupSummaryDisplayText
Return the value and the display text of the specific group summary item for a specific group.
GridView.GetGroupSummaryValues
Returns the hashtable that stores pairs of summary items (keys) and their values (values) for the given row handle. The hashtable contains entries for summary items displayed in both group footers and group rows.
GridView.GetGroupSummaryText
Returns the text, displayed by group summary items in a group row.
GridView.GetRowFooterCellText
Call this method to retrieve text, displayed by a specific summary item in a group footer.
Example
The following code utilizes summary access API to perform the following customizations:
- groups with more than three child items are highlighted with red;
- display text of total summaries is changed without modifying these summaries' display formats.

C# |
using DevExpress.XtraGrid.Views.Grid;
private void gridView_RowStyle(object sender, DevExpress.XtraGrid.Views.Grid.RowStyleEventArgs e) {
GridView view = sender as GridView;
if (view == null) return;
if (e.RowHandle >= 0 || view.GroupCount == 0) return;
Hashtable ht = view.GetGroupSummaryValues(e.RowHandle);
GridSummaryItem groupSummaryItem = view.GroupSummary[0];
int childRecordCount = Convert.ToInt32(ht[groupSummaryItem]);
if (childRecordCount > 3)
e.Appearance.BackColor = Color.FromArgb(70, Color.Red);
}
private void gridView_CustomDrawFooterCell(object sender, DevExpress.XtraGrid.Views.Grid.FooterCellCustomDrawEventArgs e) {
GridSummaryItem summary = e.Info.SummaryItem;
double summaryValue = Convert.ToDouble(summary.SummaryValue);
string summaryText = String.Format("{0} {1} = {2:c2}", summary.SummaryType, e.Column.GetCaption(), summaryValue);
e.Info.DisplayText = summaryText;
}
|
VB |
Imports DevExpress.XtraGrid.Views.Grid
Private Sub gridView_RowStyle(ByVal sender As Object, ByVal e As DevExpress.XtraGrid.Views.Grid.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
Dim ht As Hashtable = view.GetGroupSummaryValues(e.RowHandle)
Dim groupSummaryItem As GridSummaryItem = view.GroupSummary(0)
Dim childRecordCount As Integer = Convert.ToInt32(ht(groupSummaryItem))
If childRecordCount > 3 Then
e.Appearance.BackColor = Color.FromArgb(70, Color.Red)
End If
End Sub
Private Sub gridView_CustomDrawFooterCell(ByVal sender As Object, ByVal e As DevExpress.XtraGrid.Views.Grid.FooterCellCustomDrawEventArgs)
Dim summary As GridSummaryItem = e.Info.SummaryItem
Dim summaryValue As Double = Convert.ToDouble(summary.SummaryValue)
Dim summaryText As String = String.Format("{0} {1} = {2:c2}", summary.SummaryType, e.Column.GetCaption(), summaryValue)
e.Info.DisplayText = summaryText
End Sub
|
Data Grid updates its summaries when a user focuses another row, or presses the "End Init" Data Navigator button. You can disable this automatic update for total summaries to improve the overall Grid performance on large data sources. To do that, disable the GridOptionsBehavior.AutoUpdateTotalSummary setting.
If you need to forcibly update summaries, call one of the following methods.
In the following example, the "Quantity" column has a total "Count" summary. The code updates this summary immediatelly after a user has changed a value of any cell that belongs to this column.
C# |
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
|