Skip to main content

Tutorial: Custom Summary Functions

  • 4 minutes to read

This walkthrough is a transcript of the Custom Summary Functions video available on the DevExpress YouTube Channel.

The DevExpress GridControl allows you to implement custom aggregate functions to calculate total and group summaries. In this tutorial, you will create a total summary that is calculated using values from two different fields. You will also implement a custom group summary to calculate the number of records that have Discontinued a field value set to true.

GridView_Summaries_CustomSummaryFunctionsResult

Starting Point

Start with a GridControl that doesn’t have any summaries.

GridView_Summaries_InitialGridForCustomSummary

Adding a Total Summary

First, enable the View footer. Expand the GridView.OptionsView property and turn on the GridOptionsView.ShowFooter option.

After that, select the Unit Price column, expand its GridColumn.SummaryItem property and set GridSummaryItem.SummaryType to SummaryItemType.Custom. Customize text formatting using the GridSummaryItem.DisplayFormat property. Additionally, set the GridSummaryItem.Tag property to 1. This value will be used to identify this summary item in code.

GridView_Summaries_AddingCustomTotalSummary

Adding a Group Summary

Now create a new group summary. Invoke the Grid Designer, switch to the Group Summary Items Page and add a new item. Specify text formatting, set the GridSummaryItem.FieldName property to Discontinued, the GridSummaryItem.SummaryType property to SummaryItemType.Custom and the GridSummaryItem.Tag property to 2.

GridView_Summaries_AddingCustomGroupSummary

Implementing Custom Summary Calculation Algorithms

Go to the code view and declare two variables that will store summary values.

// Variables that store summary values. 
int discontinuedProductsCount;
double totalPrice;

To implement the summary calculation algorithm, handle the View’s GridView.CustomSummaryCalculate event. In the event handler, use the GridSummaryItem.Tag property to identify summary items.

private void gridView_CustomSummaryCalculate(object sender, CustomSummaryEventArgs e) {
    GridView view = sender as GridView;
    // Get the summary ID. 
    int summaryID = Convert.ToInt32((e.Item as GridSummaryItem).Tag);    
}
  • Initialization

    To allow you to initialize summary start values, the GridView.CustomSummaryCalculate event is first raised with the CustomSummaryEventArgs.SummaryProcess parameter set to CustomSummaryProcess.Start. At this stage, you can reset the counter of discontinued products and the variable that will calculate the total price of all products in stock.

    private void gridView_CustomSummaryCalculate(object sender, CustomSummaryEventArgs e) {
        // ...
        // Custom summary initialization. 
        if (e.SummaryProcess == CustomSummaryProcess.Start) {
            switch(summaryID) {
                case 1:
                    totalPrice = 0;
                    break;
                case 2:
                    discontinuedProductsCount = 0;
                    break;
            }
        }
    }    
    
  • Calculation

    Then, the GridView.CustomSummaryCalculate event fires for each data row in the View or in a group with the CustomSummaryEventArgs.SummaryProcess parameter set to CustomSummaryProcess.Calculate. This is where you can accumulate your summary values. The currently processed row and field value are specified by the event’s CustomSummaryEventArgs.RowHandle and CustomSummaryEventArgs.FieldValue parameters.

    For the total summary, you need to multiply a product’s unit price by units in stock, and add the result to the previous total price. For the group summary, increase the counter provided that a product is discontinued.

    private void gridView_CustomSummaryCalculate(object sender, CustomSummaryEventArgs e) {
        // ...
        // Custom summary calculation.
        if (e.SummaryProcess == CustomSummaryProcess.Calculate) {
            switch (summaryID) {
                case 1: // The total summary calculated against the 'UnitPrice' column. 
                    int unitsInStock = Convert.ToInt32(view.GetRowCellValue(e.RowHandle, "UnitsInStock"));
                    totalPrice += Convert.ToDouble(e.FieldValue) * unitsInStock;
                    break;
                case 2: // The group summary. 
                    Boolean isDiscontinued = Convert.ToBoolean(e.FieldValue);
                    if (isDiscontinued) discontinuedProductsCount++;
                    break;
            }
        }     
    }
    
  • Finalization

    The GridView.CustomSummaryCalculate event is raised one more time after processing all rows, and the CustomSummaryEventArgs.SummaryProcess parameter is set to CustomSummaryProcess.Finalize. At this stage, finalize the summary calculation and assign the summary value to the event’s CustomSummaryEventArgs.TotalValue parameter.

    private void gridView_CustomSummaryCalculate(object sender, CustomSummaryEventArgs e) {
        // ...
        // Finalization. 
        if (e.SummaryProcess == CustomSummaryProcess.Finalize) {
            switch (summaryID) {
                case 1:
                    e.TotalValue = totalPrice;
                    break;
                case 2:
                    e.TotalValue = discontinuedProductsCount;
                    break;
            }
        }      
    }
    

Run the application to see the result. The View’s footer cell under the Unit Price column displays the summary calculated against two fields at once. Group the grid’s data by the Category column. Group rows display the number of discontinued products in each group.

GridView_Summaries_CustomSummaryFunctionsResult

Complete Code

// Variables that store summary values. 
int discontinuedProductsCount;
double totalPrice;

private void gridView_CustomSummaryCalculate(object sender, CustomSummaryEventArgs e) {
    GridView view = sender as GridView;
    // Get the summary ID. 
    int summaryID = Convert.ToInt32((e.Item as GridSummaryItem).Tag);

    // Initialization. 
    if (e.SummaryProcess == CustomSummaryProcess.Start) {
        discontinuedProductsCount = 0;
        totalPrice = 0;
    }
    // Calculation.
    if (e.SummaryProcess == CustomSummaryProcess.Calculate) {
        switch (summaryID) {
            case 1: // The total summary calculated against the 'UnitPrice' column. 
                int unitsInStock = Convert.ToInt32(view.GetRowCellValue(e.RowHandle, "UnitsInStock"));
                totalPrice += Convert.ToDouble(e.FieldValue) * unitsInStock;
                break;
            case 2: // The group summary. 
                Boolean isDiscontinued = Convert.ToBoolean(e.FieldValue);
                if (isDiscontinued) discontinuedProductsCount++;
                break;
        }
    }
    // Finalization. 
    if (e.SummaryProcess == CustomSummaryProcess.Finalize) {
        switch (summaryID) {
            case 1:
                e.TotalValue = totalPrice;
                break;
            case 2:
                e.TotalValue = discontinuedProductsCount;
                break;
        }
    }      
}
See Also