Summary in Blazor Grid
- 12 minutes to read
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 calculation
- Place 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 function
- Use a summary’s SummaryType property to specify an aggregate function to calculate.
DevExpress Blazor Grid supports the following predefined functions:
Sum
,Min
,Max
,Avg
, andCount
. - A data field that supplies values for calculations
- Set the FieldName property to the name of a data field whose values are used to calculate the summary.
Min
andMax
functions support data fields whose values can be compared.Avg
andSum
functions require a numeric field.- For the
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
- The grid component can display group summaries in group rows or group footers. To display values in group footers, assign a column name to the FooterColumnName property.
- The grid component displays total summaries in the grid footer under the column that supplies values for calculations. Use the FooterColumnName property to display the summary in another column.
<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>
Custom Summary
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.
The CustomSummary event occurs multiple times as follows:
- Once, before grid rows are processed. The event argument’s SummaryStage property returns
Start
. At this stage, you can initialize a summary value. - For each data row in the processed range. The SummaryStage property returns
Calculate
. At this stage, you can calculate a summary value. - Once, after grid rows are processed. The SummaryStage property returns
Finalize
. At this stage, you can finalize summary calculation.
- Once, before grid rows are processed. The event argument’s SummaryStage property returns
(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;
}
}
}
}
Customize Summary Text
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.
Format Column Values and Summary Value in the Same Format
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>
Format Summary Value
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}" />
Format Summary Text
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.
Implement a Custom Template for Summary
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>
Obtain Summary Values
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 |
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>
Limitations
- When you use GridDevExtremeDataSource<T>, the Grid does not support a custom summary.
- When you use Server Mode data source, the CustomSummary event fires only once. The SummaryStage property returns
Finalize
. - When exporting data, the CustomizeSummaryDisplayText event does not fire. You can handle the CustomizeCell event to specify custom summary text in the exported document.
Related API
This section contains a comprehensive summary-related API reference.
Export Options | Type | Description |
---|---|---|
CalcTotalSummaryOnCompositeRange | Property | Specifies whether a total summary exported as the SUBTOTAL function 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 cell currently being processed. |
Task-Based Examples
This section contains code samples that demonstrate grid summary functionality.
Remove the Default Summary Label
You can hide default summary labels in the following ways:
Specify the summary item’s DisplayText property:
<DxGridSummaryItem DisplayText="{0}" SummaryType="GridSummaryItemType.Sum" FieldName="Total"/>
Handle the CustomizeSummaryDisplayText event and specify its DisplayText property.
void Grid_CustomizeSummaryDisplayText(GridCustomizeSummaryDisplayTextEventArgs e) { if (e.Item.Name == "Total") e.DisplayText = string.Format("{0:c}", e.Value); }
Implement a template for the element that displays a summary.
<DxGrid Data="Data"> <Columns> @* ... *@ <DxGridDataColumn FieldName="Total" DisplayFormat="c"> <FooterTemplate> @context.Grid.GetTotalSummaryFormattedValue(context.SummaryItems[0]) </FooterTemplate> </DxGridDataColumn> </Columns> <TotalSummary> <DxGridSummaryItem SummaryType="GridSummaryItemType.Sum" FieldName="Total"/> </TotalSummary> </DxGrid>
Calculate a Summary for Selected Rows
The following code sample calculates the sum of Total values of selected Grid rows:
<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();
}
}
Update Summary Values
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();
Calculate a Summary Based on Other Column’s Values (Other Summaries)
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; }
}
}
Display a Summary Outside a Grid
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();
}
}
How to Show Different Summaries for Different Group Columns
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;
}
}
Display Summaries in Group Row Tooltips
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);
}
}