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.

Data Grid - Summaries - Example 1

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.
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 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.

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 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.

Data Grid - Summaries - Example 2

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 a View assigned to 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 this this help article for more information about pattern and clone Views: Master-Detail Relationships.

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.

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.

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 code below utilizes a summary access API to customize the following:

  • groups with more than three child items are highlighted with red;
  • display text of total summaries is changed without modifying these summaries' display formats.

GridView_Summaries_ObtainTotalSummaryValueResult

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 summaries' 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.

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.

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();
    }
}
See Also