本主题描述如何实现自定义聚合函数来计算汇总。 关于汇总的基础信息,在 汇总概述 主题中提供。
总体汇总 和 分组汇总 提供了五个预定义的聚合函数。 这些函数允许计算行数、最大值、最小值、合计和平均值。 如果需要使用自定义算法来任何聚合函数来计算汇总值,则需要接管网格视图的事件,并且实现自定义汇总计算算法。
自定义汇总提供下列功能:
- 对符合特定标准的记录计算汇总
- 在计算中包含多个字段
- 实现复杂的函数 (例如,总体标准差等)。
注意,在特定情况下,可能需要稍微修改某种标准的汇总计算算法。 例如,当计算 Average 函数时,XtraGrid 把 null 值解释为零。 可能需要改变这种计算算法,来忽略包含 null 值的记录。 但是,XtraGrid 控件不允许干预标准的汇总计算。 而是需要创建一个自定义汇总 (复制标准的算法,并按需要更改)。
总说明
要人工计算汇总,则:
- 创建一个汇总项,并把它的 GridSummaryItem.SummaryType 属性设置为 SummaryItemType.Custom;
- 接管 GridView.CustomSummaryCalculate 事件,实现汇总计算算法。
GridView.CustomSummaryCalculate 事件为包含在汇总计算中的每个行发生。 当计算总体汇总值时,此事件为每个数据行发生。 当计算分组汇总值时,此事件为每个在组中的数据行发生。 另外,在处理行之前和之后,此事件发生,这可以用于执行任何初始代码和结束代码。 下面提供了更多信息。
汇总计算由三个阶段组成: Initialization、Calculation 和 Finalization。 当接管 GridView.CustomSummaryCalculate 时,可以通过读取事件的 CustomSummaryEventArgs.SummaryProcess 参数来确定当前的阶段。
-
Initialization
CustomSummaryCalculate 事件发生一次,并且 SummaryProcess 参数被设置为 CustomSummaryProcess.Start。 在此阶段,可以初始汇总的起始值 (例如,重置会累计运行总数的计数器或变量)。
-
Calculation
CustomSummaryCalculate 事件发生多次 (为视图或组中的每个行都发生一次)。 在每个事件调用期间,SummaryProcess 参数被设置为 CustomSummaryProcess.Calculate。 在此阶段,应该根据自定义逻辑来累积汇总。
当前被处理的行通过 CustomSummaryEventArgs.RowHandle 属性标识。 要获取行的取值,可以使用有一个行句柄作为参数的 GridView.GetRowCellValue 方法。
-
Finalization
CustomSummaryCalculate 事件发生一次,并且 SummaryProcess 参数被设置为 CustomSummaryProcess.Finalize。 在此阶段,计算最终汇总值,并把它指派到 CustomSummaryEventArgs.TotalValue 参数。
在特定情况下,可能需要在 Initialization 或 Finalization 阶段计算自定义汇总,而跳过耗时的 Calculation 阶段。 要这样处理,则在 Initialization 步骤把 CustomSummaryEventArgs.TotalValueReady 参数设置为 true。 如果 TotalValueReady 属性值被设置为 true,则 Calculation 阶段被跳过,并且立即启动 Finalization 阶段。
示例
下面的示例展示了如何创建两个自定义汇总,在 GridView.CustomSummaryCalculate 事件中计算它们。 假设网格控件绑定到一个包含被计算汇总的“UnitPrice”和“Discontinued”字段的数据源。 在本例中,网格的记录按照“UnitsInStock”字段分组。
第一个汇总将计算“Discontinued”字段值被设置为 true 的记录的总数。 这是一个分组汇总。 第二个汇总将按照“Discontinued”字段值被设置为 false 的记录来计算“UnitPrice”字段的合计值。 这是一个总体汇总。
本示例的最终结果显示如下:
-
自定义总体汇总
要在设计时刻初始“UnitPrice”列的总体汇总,则在网格控件中单击它的标头,并切换到“属性”窗口,现在“属性”窗口中列出了该列的设置。 把列的 GridColumn.SummaryItem 属性设置为自定义的汇总项。 设置它的属性,如下所示:
- GridSummaryItem.SummaryType 设置为 Custom;
- GridSummaryItem.DisplayFormat 设置为 "Custom Sum = {0:C2}"
- GridSummaryItem.Tag 设置为 1。
GridSummaryItem.Tag 属性用于在 GridView.CustomSummaryCalculate 事件中计算汇总时标识此汇总项。 可以为该属性指派任何值。 在本例中,指派了一个整数值 (1)。
总体汇总被显示在 视图脚注 中,在默认情况下视图脚注被隐藏。 要让它可视,则使用 GridOptionsView.ShowFooter 属性。
要在运行时刻初始化总体汇总,则使用下列代码:
C# 复制代码 colUnitPrice.SummaryItem.SummaryType = DevExpress.Data.SummaryItemType.Custom; colUnitPrice.SummaryItem.DisplayFormat = "Custom Sum = {0:C2}"; colUnitPrice.SummaryItem.Tag = 1; (colUnitPrice.View as GridView).OptionsView.ShowFooter = true;
Visual Basic 复制代码 colUnitPrice.SummaryItem.SummaryType = DevExpress.Data.SummaryItemType.Custom colUnitPrice.SummaryItem.DisplayFormat = "Custom Sum = {0:C2}" colUnitPrice.SummaryItem.Tag = 1 CType(colUnitPrice.View, GridView).OptionsView.ShowFooter = True
-
创建分组汇总
要创建分组汇总,则打开网格控件的设计器,然后切换到 “Group Summary Items(分组汇总项)”页面。 单击 Add 按钮创建一个分组汇总项,并定制它,如下所示:
- GridSummaryItem.SummaryType 设置为 Custom;
- GridSummaryItem.FieldName 设置为“Discontinued”;
- GridSummaryItem.DisplayFormat 设置为 “(Discontinued 产品 = {0})”
- GridSummaryItem.Tag 设置为 2。
必须把在运行时刻创建的分组汇总项,人工添加到 GridView.GroupSummary 集合中。 下列代码展示了如何通过代码创建一个分组汇总项:
C# 复制代码 GridGroupSummaryItem item = new GridGroupSummaryItem(); item.FieldName = "Discontinued"; item.SummaryType = DevExpress.Data.SummaryItemType.Custom; item.DisplayFormat = "(Discontinued products = {0})"; item.Tag = 2; gridView1.GroupSummary.Add(item);
Visual Basic 复制代码 Dim Item As New GridGroupSummaryItem() Item.FieldName = "Discontinued" Item.SummaryType = DevExpress.Data.SummaryItemType.Custom Item.DisplayFormat = "(Discontinued products = {0})" Item.Tag = 2 GridView1.GroupSummary.Add(Item)
-
自定义汇总计算
最后的步骤是通过 GridView.CustomSummaryCalculate 事件实现自定义汇总计算。 为 GridSummaryItem.SummaryType 属性值设置为 Custom 的每个汇总项,此事件都被调用。 为了识别特定的汇总项,在本例中使用了它们的 GridSummaryItem.Tag 属性。
C# 复制代码 using DevExpress.Data; // The variables that will store summary values. int discontinuedProductsCount; decimal customSum; private void gridView1_CustomSummaryCalculate(object sender, CustomSummaryEventArgs e) { // Get the summary ID. int summaryID = Convert.ToInt32((e.Item as GridSummaryItem).Tag); GridView View = sender as GridView; // Initialization if(e.SummaryProcess == CustomSummaryProcess.Start) { discontinuedProductsCount = 0; customSum = 0; } // Calculation if(e.SummaryProcess == CustomSummaryProcess.Calculate) { bool isDiscontinued = (bool)View.GetRowCellValue(e.RowHandle, "Discontinued"); switch(summaryID) { case 1: // The total summary calculated against the 'UnitPrice' column. if(!isDiscontinued) customSum += Convert.ToDecimal(e.FieldValue); break; case 2: // The group summary. if(isDiscontinued) discontinuedProductsCount++; break; } } // Finalization if(e.SummaryProcess == CustomSummaryProcess.Finalize) { switch(summaryID) { case 1: e.TotalValue = customSum; break; case 2: e.TotalValue = discontinuedProductsCount; break; } } }
Visual Basic 复制代码 ' The variables that will store summary values. Dim discontinuedProductsCount As Integer Dim customSum As Decimal Private Sub GridView1_CustomSummaryCalculate1(ByVal sender As Object, ByVal e As _ DevExpress.Data.CustomSummaryEventArgs) Handles GridView1.CustomSummaryCalculate ' Get the summary ID. Dim summaryID As Integer = Convert.ToInt32(CType(e.Item, GridSummaryItem).Tag) Dim View As GridView = CType(sender, GridView) ' Initialization If e.SummaryProcess = CustomSummaryProcess.Start Then discontinuedProductsCount = 0 customSum = 0 End If ' Calculation If e.SummaryProcess = CustomSummaryProcess.Calculate Then Dim isDiscontinued As Boolean = CBool(View.GetRowCellValue(e.RowHandle, "Discontinued")) Select Case summaryID Case 1 ' The total summary calculated against the 'UnitPrice' column. If Not isDiscontinued Then customSum += Convert.ToDecimal(e.FieldValue) Case 2 ' The group summary. If isDiscontinued Then discontinuedProductsCount += 1 End Select End If ' Finalization If e.SummaryProcess = CustomSummaryProcess.Finalize Then Select Case summaryID Case 1 e.TotalValue = customSum Case 2 e.TotalValue = discontinuedProductsCount End Select End If End Sub
现在如果运行项目,则结果与下面的插图相像:
本示例的完整代码在下面展示:
C# | 复制代码 |
---|---|
using DevExpress.Data; using DevExpress.XtraGrid; using DevExpress.XtraGrid.Views.Grid; // Customize the total summary. colUnitPrice.SummaryItem.SummaryType = DevExpress.Data.SummaryItemType.Custom; colUnitPrice.SummaryItem.DisplayFormat = "Custom Sum = {0:C2}"; colUnitPrice.SummaryItem.Tag = 1; (colUnitPrice.View as GridView).OptionsView.ShowFooter = true; // Create the group summary. GridGroupSummaryItem item = new GridGroupSummaryItem(); item.FieldName = "Discontinued"; item.SummaryType = DevExpress.Data.SummaryItemType.Custom; item.DisplayFormat = "(Discontinued products = {0})"; item.Tag = 2; gridView1.GroupSummary.Add(item); // The variables that will store summary values. int discontinuedProductsCount; decimal customSum; private void gridView1_CustomSummaryCalculate(object sender, CustomSummaryEventArgs e) { // Get the summary ID. int summaryID = Convert.ToInt32((e.Item as GridSummaryItem).Tag); GridView View = sender as GridView; // Initialization if(e.SummaryProcess == CustomSummaryProcess.Start) { discontinuedProductsCount = 0; customSum = 0; } // Calculation if(e.SummaryProcess == CustomSummaryProcess.Calculate) { bool isDiscontinued = (bool)view.GetRowCellValue(e.RowHandle, "Discontinued"); switch(summaryID) { case 1: // The total summary calculated against the 'UnitPrice' column. if(!isDiscontinued) customSum += Convert.ToDecimal(e.FieldValue); break; case 2: // The group summary. if(isDiscontinued) discontinuedProductsCount++; break; } } // Finalization if(e.SummaryProcess == CustomSummaryProcess.Finalize) { switch(summaryID) { case 1: e.TotalValue = customSum; break; case 2: e.TotalValue = discontinuedProductsCount; break; } } } |
Visual Basic | 复制代码 |
---|---|
Imports DevExpress.Data Imports DevExpress.XtraGrid Imports DevExpress.XtraGrid.Views.Grid ' Customize the total summary. colUnitPrice.SummaryItem.SummaryType = DevExpress.Data.SummaryItemType.Custom colUnitPrice.SummaryItem.DisplayFormat = "Custom Sum = {0:C2}" colUnitPrice.SummaryItem.Tag = 1 CType(colUnitPrice.View, GridView).OptionsView.ShowFooter = True ' Create the group summary. Dim Item As New GridGroupSummaryItem Item.FieldName = "Discontinued" Item.SummaryType = DevExpress.Data.SummaryItemType.Custom Item.DisplayFormat = "(Discontinued products = {0})" Item.Tag = 2 GridView1.GroupSummary.Add(Item) ' The variables that will store summary values. Dim discontinuedProductsCount As Integer Dim customSum As Decimal Private Sub GridView1_CustomSummaryCalculate1(ByVal sender As Object, ByVal e As _ DevExpress.Data.CustomSummaryEventArgs) Handles GridView1.CustomSummaryCalculate ' Get the summary ID. Dim summaryID As Integer = Convert.ToInt32(CType(e.Item, GridSummaryItem).Tag) Dim View As GridView = CType(sender, GridView) ' Initialization If e.SummaryProcess = CustomSummaryProcess.Start Then discontinuedProductsCount = 0 customSum = 0 End If ' Calculation If e.SummaryProcess = CustomSummaryProcess.Calculate Then Dim isDiscontinued As Boolean = CBool(view.GetRowCellValue(e.RowHandle, "Discontinued")) Select Case summaryID Case 1 ' The total summary calculated against the 'UnitPrice' column. If Not isDiscontinued Then customSum += Convert.ToDecimal(e.FieldValue) Case 2 ' The group summary. If isDiscontinued Then discontinuedProductsCount += 1 End Select End If ' Finalization If e.SummaryProcess = CustomSummaryProcess.Finalize Then Select Case summaryID Case 1 e.TotalValue = customSum Case 2 e.TotalValue = discontinuedProductsCount End Select End If End Sub |