blazor-404471-components-grid-data-shaping-summary.md
Summaries calculate aggregate functions for groups of rows.
The DxGrid component maintains summaries as objects of the DxGridSummaryItem class. You can specify the following summary item settings:
Rows included in calculationPlace a summary item in the GroupSummary template to calculate a summary across rows in a group, or to the TotalSummary template to calculate a summary across all grid rows.Aggregate functionUse a summary’s SummaryType property to specify an aggregate function to calculate. DevExpress Blazor Grid supports the following predefined functions: Sum, Min, Max, Avg, and Count.A data field that supplies values for calculationsSet the FieldName property to the name of a data field whose values are used to calculate the summary.
Min and Max functions support data fields whose values can be compared.Avg and Sum functions require a numeric field.Count function, you can use either the FieldName or FooterColumnName property to specify which column displays the summary value.A column that displays the summary
<DxGrid Data="Data">
<Columns>
<DxGridDataColumn FieldName="CompanyName" />
<DxGridDataColumn FieldName="City" />
<DxGridDataColumn FieldName="Country" GroupIndex="0" />
<DxGridDataColumn FieldName="UnitPrice" DisplayFormat="c" />
<DxGridDataColumn FieldName="Quantity" />
<DxGridDataColumn FieldName="Total" DisplayFormat="c"
UnboundType="GridUnboundColumnType.Decimal"
UnboundExpression="[UnitPrice] * [Quantity]" />
</Columns>
<GroupSummary>
<DxGridSummaryItem SummaryType="GridSummaryItemType.Count" />
<DxGridSummaryItem SummaryType="GridSummaryItemType.Sum" FieldName="Total" FooterColumnName="Total" />
</GroupSummary>
<TotalSummary>
<DxGridSummaryItem SummaryType="GridSummaryItemType.Count" FooterColumnName="CompanyName" />
<DxGridSummaryItem SummaryType="GridSummaryItemType.Avg" FieldName="Quantity" ValueDisplayFormat="n2" />
<DxGridSummaryItem SummaryType="GridSummaryItemType.Sum" FieldName="Total"/>
</TotalSummary>
</DxGrid>
DevExpress Grid for Blazor allows you to calculate group and total summaries based on custom logic. To create a custom summary, follow the steps below:
Declare a DxGridSummaryItem object in the GroupSummary or TotalSummary template.
Set the SummaryType property to Custom.
Handle the CustomSummary event to implement the summary calculation algorithm.
(Optional). You may need to update summary values more often than the component does. For example, if you want to display summaries based on selected rows, you need to run calculations every time selection changes. In such cases, call the RefreshSummary() method when necessary.
(Optional). Specify the DisplayText property or handle the CustomizeSummaryDisplayText event to change the summary’s display text.
Note
The Grid does not support custom summary when you use GridDevExtremeDataSource.
If you use Server Mode data source, the CustomSummary event fires only once. The SummaryStage property returns Finalize.
In the following example, a custom summary calculates the median for Unit Price column values:
@inject NwindDataService NwindDataService
<DxGrid Data="GridData" CustomSummary="Grid_CustomSummary">
<Columns>
<DxGridDataColumn FieldName="OrderId" />
<DxGridDataColumn FieldName="OrderDate" />
<DxGridDataColumn FieldName="ProductName" />
<DxGridDataColumn FieldName="UnitPrice" DisplayFormat="c2" />
</Columns>
<TotalSummary>
<DxGridSummaryItem FieldName="UnitPrice" DisplayText="Median: {0}"
SummaryType="GridSummaryItemType.Custom" />
<DxGridSummaryItem SummaryType="GridSummaryItemType.Avg" FieldName="UnitPrice" />
</TotalSummary>
</DxGrid>
@code {
IEnumerable<Invoice> GridData { get; set; }
protected override async Task OnInitializedAsync() {
GridData = await NwindDataService.GetInvoicesAsync();
}
void Grid_CustomSummary(GridCustomSummaryEventArgs e) {
IEnumerable<Invoice> OrderedData = GridData.OrderBy(i => i.UnitPrice);
if(e.SummaryStage== GridCustomSummaryStage.Finalize) {
int count = OrderedData.Count();
if(count % 2 == 0) {
var invoice1 = (Invoice)OrderedData.Skip(count / 2 - 1).Take(1).First();
var invoice2 = (Invoice)OrderedData.Skip(count / 2).Take(1).First();
e.TotalValue = (invoice1.UnitPrice + invoice2.UnitPrice) / 2;
}
else {
var invoice = (Invoice)OrderedData.Skip(count / 2).Take(1).First();
e.TotalValue = invoice.UnitPrice;
}
}
}
}
DevExpress Blazor Grid constructs display text for a summary item based on the following predefined display formats:
<aggregate function>: <summary value>For the Count summary and summaries that are shown in a footer of the same column where the values are calculated.
Example: Max: 130<aggregate function> of <column caption>: <summary value>For summaries that are shown in group rows or in a footer of another column.
Example: Max of Quantity: 130
You can modify summary text strings in the following ways.
Use the EditSettings.DisplayFormat or DxGridDataColumn.DisplayFormat property to specify display format for column values. This format applies to column summary value as well.
<Columns>
<DxGridDataColumn FieldName="Total" DisplayFormat="c" />
@* ... *@
</Columns>
<TotalSummary>
<DxGridSummaryItem SummaryType="GridSummaryItemType.Sum" FieldName="Total" />
</TotalSummary>
Specify the ValueDisplayFormat property to format the calculated summary value (the <summary value> part). The summary value pattern can include static text mixed with an indexed placeholder ( {0} ) that corresponds to the calculated summary value.
<DxGridSummaryItem SummaryType="GridSummaryItemType.Avg" FieldName="Quantity" ValueDisplayFormat="n2" />
<DxGridSummaryItem SummaryType="GridSummaryItemType.Sum" FieldName="Total" ValueDisplayFormat="~${0:n0}" />
A summary item’s DisplayText property allows you to specify display text pattern for this summary. A display text string can include static text and placeholders for summary value and column caption.
<DxGrid Data="Data">
<Columns>
<DxGridDataColumn FieldName="CompanyName" />
<DxGridDataColumn FieldName="UnitPrice" DisplayFormat="c" Width="10%" />
<DxGridDataColumn FieldName="Quantity" Width="10%" />
<DxGridDataColumn FieldName="Total" UnboundType="GridUnboundColumnType.Decimal"
UnboundExpression="[UnitPrice] * [Quantity]" DisplayFormat="${0:n2}" />
</Columns>
<TotalSummary>
<DxGridSummaryItem FieldName="Total" SummaryType="GridSummaryItemType.Min"
DisplayText="The cheapest order is {0}" />
<DxGridSummaryItem FieldName="Total" SummaryType="GridSummaryItemType.Max"
DisplayText="The most expensive order is is {0}" />
</TotalSummary>
</DxGrid>
To customize display text for an individual calculated summary value, handle the CustomizeSummaryDisplayText event. The Grid event argument allows you to obtain information about the Grid’s current state and add this information to a summary item’s display text.
You can specify the following template properties to implement custom content for elements that contain summaries.
| Element | Grid-Level Property | Column-Level Property |
|---|---|---|
| Group Row | DataColumnGroupRowTemplate | GroupRowTemplate |
| Column Group Footer | ColumnGroupFooterTemplate | GroupFooterTemplate |
| Column Footer | ColumnFooterTemplate | FooterTemplate |
<DxGridDataColumn FieldName="ID">
<FooterTemplate>
Total:
</FooterTemplate>
</DxGridDataColumn>
DevExpress Grid for Blazor implements methods that obtain group and total summary text and value. You can use these methods to display a summary in a template or in a separate control.
| Name | Group Summary Method | Total Summary Method | Return Value |
|---|---|---|---|
| Display Text | GetGroupSummaryDisplayText | GetTotalSummaryDisplayText | Avg of Unit Price: $26.22 |
| Label | GetGroupSummaryLabel | GetTotalSummaryLabel | Avg of Unit Price |
| Formatted Value | GetGroupSummaryFormattedValue | GetTotalSummaryFormattedValue | $26.22 |
| Value | GetGroupSummaryValue | GetTotalSummaryValue | 26.21851972157772621809744 |
Run Demo: Grid - Group Row Template
The following code snippet customizes group row content.
<DxGridDataColumn FieldName="Country" GroupIndex="0" Width="10%">
<GroupRowTemplate>
<text>@context.ColumnCaption: @context.GroupValue</text>
@{
var summaryItems = context.Grid.GetGroupSummaryItems();
if(summaryItems.Any()) {
<text> (</text>
foreach(var i in summaryItems) {
if(i != summaryItems.First()) {
<text>, </text>
}
@context.Grid.GetGroupSummaryLabel(i, context.VisibleIndex)
<text>: </text>
<b>@context.Grid.GetGroupSummaryFormattedValue(i, context.VisibleIndex)</b>
}
<text>)</text>
}
}
</GroupRowTemplate>
</DxGridDataColumn>
@* ... *@
<GroupSummary>
<DxGridSummaryItem SummaryType="GridSummaryItemType.Sum" FieldName="Total" />
<DxGridSummaryItem SummaryType="GridSummaryItemType.Count" FieldName="CompanyName" />
</GroupSummary>
Finalize.This section contains a comprehensive summary-related API reference.
Show API Reference
| Export Options | Type | Description |
|---|---|---|
| CalcTotalSummaryOnCompositeRange | Property | Specifies whether a total summary exported as the SUBTOTAL function that excludes references to cells with group summary values. |
| CountBlankCellsInSummary | Property | Specifies whether the Count summary function takes blank cells into account when exporting data in Excel formats. |
| SummaryItem | Event Property | Returns information on the summary calculated in the currently processed cell. |
This section contains code samples that demonstrate grid summary functionality.
You can hide default summary labels in the following ways:
Specify the summary item’s DisplayText property:
Handle the CustomizeSummaryDisplayText event and specify its DisplayText property.
Implement a template for the element that displays a summary.
The following code sample calculates the sum of Total values of selected Grid rows:
Run Demo: Grid - Custom Summary
<DxGrid @ref="Grid"
Data="@Data"
SelectedDataItems="@SelectedDataItems"
SelectedDataItemsChanged="Grid_SelectedDataItemsChanged"
CustomSummary="Grid_CustomSummary"
CustomizeSummaryDisplayText="Grid_CustomizeSummaryDisplayText">
<Columns>
<DxGridSelectionColumn />
<DxGridDataColumn FieldName="OrderId" Caption="Order ID"/>
<DxGridDataColumn FieldName="CustomerId" Caption="Customer">
<EditSettings>
<DxComboBoxSettings Data="Customers" ValueFieldName="CustomerId" TextFieldName="ContactName"/>
</EditSettings>
</DxGridDataColumn>
<DxGridDataColumn FieldName="OrderDate" />
<DxGridDataColumn FieldName="ShipCountry" />
<DxGridDataColumn FieldName="ShipCity" />
<DxGridDataColumn FieldName="ShippedDate" />
<DxGridDataColumn FieldName="Total" DisplayFormat="c" />
</Columns>
<TotalSummary>
<DxGridSummaryItem SummaryType="GridSummaryItemType.Custom" Name="Custom" FieldName="Total" />
<DxGridSummaryItem SummaryType="GridSummaryItemType.Sum"
FieldName="Total"
DisplayText="Grand Total: {0}"
ValueDisplayFormat="c0" />
</TotalSummary>
</DxGrid>
@code {
IEnumerable<object> Data { get; set; }
IReadOnlyList<Customer> Customers { get; set; }
IReadOnlyList<object> SelectedDataItems { get; set; }
IGrid Grid { get; set; }
@* ... *@
void Grid_CustomSummary(GridCustomSummaryEventArgs e) {
switch(e.SummaryStage) {
case GridCustomSummaryStage.Start:
e.TotalValue = 0m;
break;
case GridCustomSummaryStage.Calculate:
if(e.Grid.IsDataItemSelected(e.DataItem))
e.TotalValue = (decimal)e.TotalValue + (decimal)e.GetRowValue("Total");
break;
}
}
void Grid_CustomizeSummaryDisplayText(GridCustomizeSummaryDisplayTextEventArgs e) {
if(e.Item.Name == "Custom")
e.DisplayText = string.Format("Sum of Selected ({0}): {1:c0}", SelectedDataItems.Count, e.Value);
}
void Grid_SelectedDataItemsChanged(IReadOnlyList<object> newSelection) {
SelectedDataItems = newSelection;
Grid.RefreshSummary();
}
}
If you implement a custom summary that can change its value dynamically, call the RefreshSummary() method to update the grid’s summary values.
Grid.RefreshSummary();
Call the GetRowValue(String) method in the CustomSummary event to calculate a summary value based on other column values.
<DxGrid Data="Data"
CustomSummary="Grid_CustomSummary"
CustomizeSummaryDisplayText="Grid_CustomizeSummaryDisplayText">
<Columns>
<DxGridDataColumn FieldName="ID">
<FooterTemplate>
Total:
</FooterTemplate>
</DxGridDataColumn>
<DxGridDataColumn FieldName="Revenue" DisplayFormat="c" />
<DxGridDataColumn FieldName="Margin" DisplayFormat="c" />
<DxGridDataColumn FieldName="MarginPercentage" Caption="Margin, %" DisplayFormat="p0"
UnboundType="GridUnboundColumnType.Decimal"
UnboundExpression="[Margin] / [Revenue]" />
</Columns>
<TotalSummary>
<DxGridSummaryItem FieldName="Margin" SummaryType="GridSummaryItemType.Sum" />
<DxGridSummaryItem FieldName="Revenue" SummaryType="GridSummaryItemType.Sum" />
<DxGridSummaryItem FieldName="MarginPercentage" SummaryType="GridSummaryItemType.Custom" />
</TotalSummary>
</DxGrid>
@code {
object Data { get; set; }
decimal marginTotal = 0m;
decimal revenueTotal = 0m;
protected override void OnInitialized() {
Data = new List<MyData> {
new MyData { ID = 1, Revenue = 40, Margin = 10 },
new MyData { ID = 2, Revenue = 50, Margin = 20 },
new MyData { ID = 3, Revenue = 110, Margin = 30 },
new MyData { ID = 4, Revenue = 70, Margin = 25 }
};
}
void Grid_CustomSummary(GridCustomSummaryEventArgs e) {
if (e.Item.FieldName == "MarginPercentage") {
switch (e.SummaryStage) {
case GridCustomSummaryStage.Start:
marginTotal = 0m;
revenueTotal = 0m;
break;
case GridCustomSummaryStage.Calculate:
marginTotal += (decimal)e.GetRowValue("Margin");
revenueTotal += (decimal)e.GetRowValue("Revenue");
break;
case GridCustomSummaryStage.Finalize:
e.TotalValue = marginTotal / revenueTotal;
break;
}
}
}
void Grid_CustomizeSummaryDisplayText(GridCustomizeSummaryDisplayTextEventArgs e) {
if (e.Item.FieldName == "Margin" || e.Item.FieldName == "Revenue")
e.DisplayText = string.Format("{0:c}", e.Value);
else if (e.Item.FieldName == "MarginPercentage")
e.DisplayText = string.Format("{0:p0}", e.Value);
}
class MyData {
public int ID { get; set; }
public decimal Revenue { get; set; }
public decimal Margin { get; set; }
}
}
The grid component implements methods that obtain group and total summary text and value. See the following section for the list of available methods: Obtain Summary Values.
The following code snippet calls the GetTotalSummaryFormattedValue method to display a total summary value above the grid component.
<h3>Total: @SummaryText</h3>
<DxGrid @ref="Grid" Data="Data" >
<Columns>
<DxGridDataColumn FieldName="CompanyName" />
<DxGridDataColumn FieldName="City" />
<DxGridDataColumn FieldName="Country" />
<DxGridDataColumn FieldName="UnitPrice" DisplayFormat="c"/>
<DxGridDataColumn FieldName="Quantity" />
<DxGridDataColumn FieldName="Total" DisplayFormat="c"
UnboundType="GridUnboundColumnType.Decimal"
UnboundExpression="[UnitPrice] * [Quantity]" />
</Columns>
<TotalSummary>
<DxGridSummaryItem SummaryType="GridSummaryItemType.Sum" FieldName="Total" Visible="false" />
</TotalSummary>
</DxGrid>
@code {
object Data { get; set; }
IGrid Grid { get; set; }
string SummaryText;
// ...
protected override void OnAfterRender(bool firstRender) {
SummaryText = Grid.GetTotalSummaryFormattedValue(Grid.GetTotalSummaryItems()[0]);
StateHasChanged();
}
}
Use the DataColumnGroupRowTemplate or GroupRowTemplate property to implement different group row templates for different columns. In a template you can use DxGrid methods that obtain summary value and text. The available methods are listed in the following section: Obtain Summary Values.
<DxGrid @ref="Grid" Data="Data" >
<Columns>
<DxGridDataColumn FieldName="Country" GroupIndex="0" />
<DxGridDataColumn FieldName="City" GroupIndex="1" />
<DxGridDataColumn FieldName="CompanyName" />
<DxGridDataColumn FieldName="UnitPrice" DisplayFormat="c" />
<DxGridDataColumn FieldName="Quantity" />
<DxGridDataColumn FieldName="Total" DisplayFormat="c"
UnboundType="GridUnboundColumnType.Decimal"
UnboundExpression="[UnitPrice] * [Quantity]" />
</Columns>
<DataColumnGroupRowTemplate>
<text>@context.ColumnCaption: @context.GroupValueDisplayText</text>
@{
var summaryItems = GetGroupSummaryItems(context);
if(summaryItems.Any()) {
<text> (</text>
foreach(var i in summaryItems) {
if(i != summaryItems.First()) {
<text>, </text>
}
@context.Grid.GetGroupSummaryLabel(i, context.VisibleIndex)
<text>: </text>
@context.Grid.GetGroupSummaryFormattedValue(i, context.VisibleIndex)
}
<text>)</text>
}
}
</DataColumnGroupRowTemplate>
<GroupSummary>
<DxGridSummaryItem SummaryType="GridSummaryItemType.Count" />
<DxGridSummaryItem SummaryType="GridSummaryItemType.Sum" FieldName="Total" />
</GroupSummary>
</DxGrid>
@code {
object Data { get; set; }
IGrid Grid { get; set; }
// ...
IReadOnlyList<IGridSummaryItem> GetGroupSummaryItems(GridDataColumnGroupRowTemplateContext context) {
var items = context.Grid.GetGroupSummaryItems();
if(context.DataColumn.FieldName == "Country")
return items.Where(i => i.SummaryType == GridSummaryItemType.Sum).ToList();
if(context.DataColumn.FieldName == "City")
return items.Where(i => i.SummaryType == GridSummaryItemType.Count).ToList();
return items;
}
}
Handle the CustomizeElement event to add a title attribute to group rows. Call the GetGroupSummaryItems method to get a group’s summary items and GetGroupSummaryDisplayText method to get an item’s display text.
void Grid_CustomizeElement(GridCustomizeElementEventArgs e) {
if(e.ElementType == GridElementType.GroupRow && e.Column.Name == "Country") {
var summaryItems = e.Grid.GetGroupSummaryItems().Select(i => e.Grid.GetGroupSummaryDisplayText(i, e.VisibleIndex));
e.Attributes["title"] = string.Join(", ", summaryItems);
}
}