Working with Summaries in Code -- Custom Summaries
- 10 minutes to read
Create Total Summaries
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 that displays total record count; does not require setting the GridSummaryItem.FieldName property.
- A summary item that calculates an average length; utilizes a custom {0:#.#} display format.
- A summary item with a custom aggregate function.
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";
For the third summary item, you need to calculate 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.
int dateCount = 0;
gridView.CustomSummaryCalculate += (sender, e) => {
if (e.IsTotalSummary) {
GridView view = sender as GridView;
switch (e.SummaryProcess) {
// Calculation entry point
case CustomSummaryProcess.Start:
dateCount = 0;
break;
// Consequent calculations
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;
// Retrieve weeks
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;
// Final summary value
case CustomSummaryProcess.Finalize:
e.TotalValue = dateCount;
break;
}
}
};
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.
gridView.Columns["ID"].Summary.Add(siTotal);
gridView.Columns["RecordDate"].Summary.Add(siRecordDate);
gridView.Columns["Length"].Summary.Add(siAverage);
gridView.OptionsView.ShowFooter = true;
Create Group Summaries
The code below creates the following 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 the 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.
// "Count" summary item
GridGroupSummaryItem gscCount = new GridGroupSummaryItem();
gscCount.SummaryType = SummaryItemType.Count;
gscCount.DisplayFormat = "({0} records)";
gridView.GroupSummary.Add(gscCount);
// "Average" summary item
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.
int dateCount = 0;
gridView.CustomSummaryCalculate += (sender, e) => {
if (e.IsGroupSummary) {
GridView view = sender as GridView;
switch (e.SummaryProcess) {
// Calculation entry point
case CustomSummaryProcess.Start:
dateCount = 0;
break;
// Consequent calculations
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;
// Retrieve weeks
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;
// Final summary value
case CustomSummaryProcess.Finalize:
e.TotalValue = dateCount;
break;
}
}
};
gridView.GroupSummary.Add(SummaryItemType.Custom, "RecordDate", gridView.Columns["RecordDate"], "{0} this week");
Obtain Summary Values
Utilize the following API to retrieve summaries, their values, and displayed text.
Note
In master-detail mode, when a master row is expanded, the Data Grid creates a copy of the View assigned to the detail Data Grid level (pattern View), and uses this copy to display detail data. Pattern Views only store settings; they are never connected to data. To access detail View summary values, use columns and summaries of pattern View copies (clone Views). See the “Patterns and Clones” section of the following help topic for more information about pattern and clone Views: Master-Detail Relationships.
Common API
Gets the value of this summary item.
GridSummaryItem.GetDisplayText
Applies the current display format rule expression to convert any value into display text.
Total Summaries
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
Takes a row handle and a column as parameters and returns a DictionaryEntry object that provides access to:
- 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.
The code sample below retrieves a group summary item’s text whenever the focused row changes.
using DevExpress.XtraGrid.Views.Base;
private void gridView1_FocusedRowChanged(object sender, FocusedRowChangedEventArgs e) {
GridView currentView = sender as GridView;
// Obtain the summary item displayed in the focused column
// within the focused group row's footer.
DictionaryEntry ent = currentView.GetRowSummaryItem(e.FocusedRowHandle,
currentView.FocusedColumn);
// Determine whether the summary item for the specified row and
// column is successfully obtained.
if(ent.Key != null) {
GridGroupSummaryItem si = (GridGroupSummaryItem)ent.Key;
// Obtain the summary item's text.
this.Text = si.GetDisplayText(ent.Value, true);
} else {
this.Text = "There is no summary for this row and column";
}
}
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.
Returns the text displayed by group summary items in a group row.
Call this method to retrieve text displayed by a specific summary item in a group footer.
Example
The code below utilizes a summary access API to customize the following:
- Groups with more than three child items are highlighted in red.
- Display text of total summaries is changed without modifying the display formats of these summaries.
using DevExpress.XtraGrid.Views.Grid;
// ...
// Highlight group rows for groups with more than three records.
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;
// Get all group summary values.
Hashtable ht = view.GetGroupSummaryValues(e.RowHandle);
// Access the first group summary.
GridSummaryItem groupSummaryItem = view.GroupSummary[0];
// Obtain the group summary's value.
int childRecordCount = Convert.ToInt32(ht[groupSummaryItem]);
if (childRecordCount > 3)
e.Appearance.BackColor = Color.FromArgb(70, Color.Red);
}
// Modify total summary captions.
private void gridView_CustomDrawFooterCell(object sender, DevExpress.XtraGrid.Views.Grid.FooterCellCustomDrawEventArgs e) {
GridSummaryItem summary = e.Info.SummaryItem;
// Obtain the total summary's value.
double summaryValue = Convert.ToDouble(summary.SummaryValue);
string summaryText = String.Format("{0} {1} = {2:c2}", summary.SummaryType, e.Column.GetCaption(), summaryValue);
e.Info.DisplayText = summaryText;
}
Manually update summaries
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:
- GridView.UpdateTotalSummary() — Recalculates values for all total summaries.
- GridView.UpdateGroupSummary() — Recalculates values for all group summaries.
- GridView.UpdateSummary() — Updates both total and group summaries.
In the following example, the “Quantity” column has a total “Count” summary. The code updates this summary immediately after a user has changed a value of any cell that belongs to this column.
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();
}
}