blazor-405038-components-treelist-data-shaping-summary.md
The Blazor TreeList component can calculate total summaries and display results in the footer. To add summaries, declare DxTreeListSummaryItem objects in the TotalSummary template and specify the following summary item settings:
Aggregate functionUse a summary’s SummaryType property to specify an aggregate function to calculate. DevExpress Blazor TreeList 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.
Count function supports data fields of all types.Min and Max functions support data fields whose values can be compared.Avg and Sum functions require a numeric field.A column that displays the summaryThe TreeList component displays total summaries in the TreeList footer under the column that supplies values for calculations. Use the FooterColumnName property to display the summary in another column.
The following example calculates total summaries for TreeList columns:
@inject EmployeeTaskService EmployeeTaskService
<DxTreeList Data="TreeListData" KeyFieldName="Id" ParentKeyFieldName="ParentId">
<Columns>
<DxTreeListDataColumn FieldName="Name" Caption="Task" />
<DxTreeListDataColumn FieldName="EmployeeName" />
<DxTreeListDataColumn FieldName="StartDate" />
<DxTreeListDataColumn FieldName="DueDate" />
<DxTreeListDataColumn FieldName="Status" Caption="Progress" DisplayFormat="p0" />
</Columns>
<TotalSummary>
<DxTreeListSummaryItem SummaryType="TreeListSummaryItemType.Count" FieldName="Name" />
<DxTreeListSummaryItem SummaryType="TreeListSummaryItemType.Min" FieldName="DueDate" ValueDisplayFormat="y" />
<DxTreeListSummaryItem SummaryType="TreeListSummaryItemType.Max" FieldName="DueDate" ValueDisplayFormat="y" />
<DxTreeListSummaryItem SummaryType="TreeListSummaryItemType.Avg" FieldName="Status" />
</TotalSummary>
</DxTreeList>
@code {
List<EmployeeTask> TreeListData { get; set; }
protected override void OnInitialized() {
TreeListData = EmployeeTaskService.GenerateData();
}
}
public class EmployeeTask {
public int Id { get; set; }
public int ParentId { get; set; }
public string Name { get; set; }
public string EmployeeName { get; set; }
public DateTime StartDate { get; set; }
public DateTime DueDate { get; set; }
public int Progress { get; set; }
public EmployeeTask() { }
public EmployeeTask(
int id,
int parentId,
string name,
string employeeName,
DateTime startDate,
DateTime dueDate,
int progress
)
{
Id = id;
ParentId = parentId;
Name = name;
EmployeeName = employeeName;
StartDate = startDate;
DueDate = dueDate;
Progress = progress;
}
}
public class EmployeeTaskService {
public List<EmployeeTask> GenerateData() {
return new List<EmployeeTask>() {
new EmployeeTask(1, 0, "Simplify & Clarify Product Messaging", "John Heart", new DateTime(2018, 4, 3), new DateTime(2018, 4, 14), 14),
new EmployeeTask(2, 1, "Prepare Financial Reports", "Samantha Bright", new DateTime(2018, 4, 3), new DateTime(2018, 4, 7), 17),
new EmployeeTask(3, 1, "Prepare Marketing Plan", "Arthur Miller", new DateTime(2018, 4, 7), new DateTime(2018, 4, 14), 11),
new EmployeeTask(4, 0, "Create Action Plan to Improve Customer Engagement", "Robert Reagan", new DateTime(2017, 8, 8), new DateTime(2018, 4, 8), 23),
new EmployeeTask(5, 4, "Update Personnel Files", "Greta Sims", new DateTime(2017, 8, 8), new DateTime(2017, 10, 18), 100),
new EmployeeTask(6, 4, "Review Health Insurance Options", "Brett Wade", new DateTime(2017, 9, 27), new DateTime(2017, 11, 10), 37),
new EmployeeTask(7, 4, "Choose Between PPO and HMO Health Plan", "Sandra Johnson", new DateTime(2017, 12, 13), new DateTime(2018, 3, 23), 17),
new EmployeeTask(8, 4, "Update Google Adwords Strategy", "Ed Holmes", new DateTime(2017, 8, 23), new DateTime(2017, 12, 23), 45),
new EmployeeTask(9, 4, "Create New Brochure Design", "Barb Banks", new DateTime(2018, 1, 3), new DateTime(2018, 3, 14), 17),
new EmployeeTask(10, 4, "Obtain Price Quote for New Brochure", "Kevin Carter", new DateTime(2018, 2, 1), new DateTime(2018, 3, 15), 18),
new EmployeeTask(11, 4, "Brochure Design Review", "Cindy Stanwick", new DateTime(2017, 8, 22), new DateTime(2017, 10, 28), 4),
new EmployeeTask(12, 4, "Review Website Redesign Strategy", "Sammy Hill", new DateTime(2017, 9, 16), new DateTime(2018, 3, 6), 73),
new EmployeeTask(13, 4, "Roll Out New Website", "Davey Jones", new DateTime(2017, 11, 7), new DateTime(2018, 2, 6), 9),
new EmployeeTask(14, 4, "Update Sales/Marketing Strategy", "Victor Norris", new DateTime(2017, 12, 13), new DateTime(2018, 4, 2), 5),
new EmployeeTask(15, 4, "Update Sales/Revenue Report", "Mary Stern", new DateTime(2017, 12, 25), new DateTime(2018, 4, 2), 4),
new EmployeeTask(16, 4, "Direct vs Online Sales Comparison Report", "Robin Cosworth", new DateTime(2018, 1, 2), new DateTime(2018, 3, 20), 14),
new EmployeeTask(17, 4, "Review Sales Report and Approve Modifications", "Kelly Rodriguez", new DateTime(2017, 9, 4), new DateTime(2017, 10, 30), 8),
new EmployeeTask(18, 4, "Update R&D Strategy", "James Anderson", new DateTime(2017, 11, 13), new DateTime(2017, 12, 4), 12),
new EmployeeTask(19, 4, "Discuss Updated R&D Strategy", "Antony Remmen", new DateTime(2017, 10, 29), new DateTime(2017, 12, 31), 14),
new EmployeeTask(20, 4, "Update QA Strategy", "Olivia Peyton", new DateTime(2017, 10, 31), new DateTime(2017, 11, 2), 18),
new EmployeeTask(21, 4, "Schedule Training Events", "Taylor Riley", new DateTime(2017, 11, 19), new DateTime(2018, 4, 7), 21),
new EmployeeTask(22, 4, "Approve Hiring of John Jeffers", "Amelia Harper", new DateTime(2018, 1, 7), new DateTime(2018, 4, 8), 10),
new EmployeeTask(23, 0, "Increase Average Subscription Price", "Wally Hobbs", new DateTime(2017, 8, 9), new DateTime(2017, 9, 13), 96),
new EmployeeTask(24, 23, "Update Non-Compete Agreements", "Brad Jameson", new DateTime(2017, 8, 9), new DateTime(2017, 9, 3), 96),
new EmployeeTask(25, 23, "Update Employee Records with New NDA", "Karen Goodson", new DateTime(2017, 8, 23), new DateTime(2018, 9, 10), 100)
};
}
}
// ...
builder.Services.AddSingleton<EmployeeTaskService>();
DevExpress TreeList for Blazor allows you to calculate total summaries based on custom logic. To create a custom summary, follow the steps below:
Declare a DxTreeListSummaryItem object in the 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 the 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.
In the following example, a custom summary calculates the median for March Sales column values:
@inject ISalesByRegionDataProvider SalesByRegionDataProvider
<DxTreeList Data="Data"
KeyFieldName="ID"
ParentKeyFieldName="RegionID"
CustomSummary="TreeList_CustomSummary">
<Columns>
<DxTreeListDataColumn FieldName="Region" />
<DxTreeListDataColumn FieldName="MarchSales" DisplayFormat="c0" />
<DxTreeListDataColumn FieldName="MarchChange" DisplayFormat="p2" />
<DxTreeListDataColumn FieldName="MarketShare" DisplayFormat="p0" />
</Columns>
<TotalSummary>
<DxTreeListSummaryItem FieldName="MarchChange" DisplayText="Median: {0}"
SummaryType="TreeListSummaryItemType.Custom" />
<DxTreeListSummaryItem SummaryType="TreeListSummaryItemType.Avg" FieldName="MarchChange" />
</TotalSummary>
</DxTreeList>
@code {
List<SalesByRegion> Data { get; set; }
protected override void OnInitialized() {
Data = SalesByRegionDataProvider.GenerateData();
}
void TreeList_CustomSummary(TreeListCustomSummaryEventArgs e) {
IEnumerable<SalesByRegion> OrderedData = Data.OrderBy(i => i.MarchChange);
if (e.SummaryStage == TreeListCustomSummaryStage.Finalize) {
int count = OrderedData.Count();
if (count % 2 == 0) {
var invoice1 = (SalesByRegion)OrderedData.Skip(count / 2 - 1).Take(1).First();
var invoice2 = (SalesByRegion)OrderedData.Skip(count / 2).Take(1).First();
e.TotalValue = (invoice1.MarchChange + invoice2.MarchChange) / 2;
}
else {
var invoice = (SalesByRegion)OrderedData.Skip(count / 2).Take(1).First();
e.TotalValue = invoice.MarchChange;
}
}
}
}
DevExpress Blazor TreeList 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 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 DxTreeListDataColumn.DisplayFormat property to specify display format for column values. This format applies to the column summary value as well.
<Columns>
@* ... *@
<DxTreeListDataColumn FieldName="Status" Caption="Progress" DisplayFormat="p0" />
</Columns>
<TotalSummary>
<DxTreeListSummaryItem FieldName="Status" SummaryType="TreeListSummaryItemType.Avg" />
</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.
<DxTreeListSummaryItem SummaryType="TreeListSummaryItemType.Max" FieldName="DueDate" ValueDisplayFormat="y" />
<DxTreeListSummaryItem SummaryType="TreeListSummaryItemType.Avg" FieldName="Status" ValueDisplayFormat="~{0:p0}" />
A summary item’s DisplayText property allows you to specify a display text pattern for this summary. A display text string can include static text and placeholders for summary value and column caption.
<DxTreeList Data="TreeListData" KeyFieldName="Id" ParentKeyFieldName="ParentId">
<Columns>
<DxTreeListDataColumn FieldName="Name" Caption="Task" />
<DxTreeListDataColumn FieldName="EmployeeName" />
<DxTreeListDataColumn FieldName="StartDate" />
<DxTreeListDataColumn FieldName="DueDate" />
<DxTreeListDataColumn FieldName="Status" Caption="Progress" DisplayFormat="p0" />
</Columns>
<TotalSummary>
<DxTreeListSummaryItem SummaryType="TreeListSummaryItemType.Max" FieldName="DueDate" DisplayText="Deadline: {0}" ValueDisplayFormat="y" />
<DxTreeListSummaryItem SummaryType="TreeListSummaryItemType.Avg" FieldName="Status" DisplayText="Average Progress: {0}" />
</TotalSummary>
</DxTreeList>
To customize display text for an individual calculated summary value, handle the CustomizeSummaryDisplayText event. The TreeList event argument allows you to obtain information about the TreeList’s current state and add this information to a summary item’s display text.
You can specify DxTreeList.ColumnFooterTemplate and DxTreeListColumn.FooterTemplate properties to implement custom content for footers that display summaries. The following code sample applies italic formatting to all summary values:
<ColumnFooterTemplate>
@{
var summaryItems = context.SummaryItems;
if (summaryItems.Any()) {
foreach (var i in summaryItems) {
@context.TreeList.GetTotalSummaryLabel(i)
<text>: </text>
<i>@context.TreeList.GetTotalSummaryFormattedValue(i)</i>
}
}
}
</ColumnFooterTemplate>
DevExpress TreeList for Blazor implements methods that obtain total summary text and value. You can use these methods to display a summary in a template or in a separate control.
GetTotalSummaryDisplayTextGets a total summary item’s display text. Example: Avg of Unit Price: $26.22.GetTotalSummaryLabelReturns the name of a total summary‘s function name. Example: Avg of Unit Price.GetTotalSummaryFormattedValueGets a total summary item’s formatted value. Example: $26.22.GetTotalSummaryValueGets a total summary item’s value. Example: 26.21851972157772621809744.
The following limitations apply:
This section contains a comprehensive summary-related API reference.
Show API Reference
| DxTreeList API member | Type | Description |
|---|---|---|
| TotalSummary | Property | Contains total summary items. |
| GetTotalSummaryItems() | Method | Returns the collection of total summary items. |
| GetTotalSummaryValue(ITreeListSummaryItem) | Method | Gets a total summary item’s value. |
| GetTotalSummaryDisplayText(ITreeListSummaryItem) | Method | Gets a total summary item’s display text. |
| GetTotalSummaryLabel(ITreeListSummaryItem) | Method | Returns the name of a total summary‘s function name. |
| GetTotalSummaryFormattedValue(ITreeListSummaryItem) | Method | Gets a total summary item’s formatted value. |
| RefreshSummary() | Method | Refreshes all total summary values in the TreeList. |
| CustomSummary | Event | Allows you to create custom summary items. |
| CustomizeSummaryDisplayText | Event | Allows you to customize the summary display text. |
This section contains code samples that demonstrate TreeList 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 footer that displays the summary.
The following code sample calculates the sum of March Sales values of selected TreeList rows:
@inject ISalesByRegionDataProvider SalesByRegionDataProvider
<DxTreeList @ref="TreeList"
Data="Data"
KeyFieldName="ID"
ParentKeyFieldName="RegionID"
ShowAllRows="true"
CustomSummary="TreeList_CustomSummary"
CustomizeSummaryDisplayText="TreeList_CustomizeSummaryDisplayText"
SelectedDataItemsChanged="TreeList_SelectedDataItemsChanged">
<Columns>
<DxTreeListSelectionColumn Width="50px" />
<DxTreeListDataColumn FieldName="Region" Width="15%" />
<DxTreeListDataColumn FieldName="MarchSales" DisplayFormat="c0" Width="25%" />
<DxTreeListDataColumn FieldName="SeptemberSales" DisplayFormat="c0" Width="15%" />
<DxTreeListDataColumn FieldName="MarchChange" DisplayFormat="p2" Width="15%" />
<DxTreeListDataColumn FieldName="SeptemberChange" DisplayFormat="p2" Width="15%" />
<DxTreeListDataColumn FieldName="MarketShare" DisplayFormat="p0" Width="15%" />
</Columns>
<TotalSummary>
<DxTreeListSummaryItem SummaryType="TreeListSummaryItemType.Count" FieldName="Region" />
<DxTreeListSummaryItem SummaryType="TreeListSummaryItemType.Sum" FieldName="MarchSales" />
<DxTreeListSummaryItem SummaryType="TreeListSummaryItemType.Custom" FieldName="MarchSales" Name="Custom" />
</TotalSummary>
</DxTreeList>
@code {
ITreeList TreeList { get; set; }
object Data { get; set; }
protected override void OnInitialized() {
Data = SalesByRegionDataProvider.GenerateData();
}
void TreeList_CustomSummary(TreeListCustomSummaryEventArgs e) {
switch(e.SummaryStage) {
case TreeListCustomSummaryStage.Start:
e.TotalValue = 0m;
break;
case TreeListCustomSummaryStage.Calculate:
if(e.TreeList.IsDataItemSelected(e.DataItem))
e.TotalValue = (decimal)e.TotalValue + (decimal)e.GetRowValue("MarchSales");
break;
}
}
void TreeList_CustomizeSummaryDisplayText(TreeListCustomizeSummaryDisplayTextEventArgs e) {
if(e.Item.Name == "Custom")
e.DisplayText = string.Format("Sum of Selected ({0}): {1:c0}", e.TreeList.SelectedDataItems.Count, e.Value);
}
void TreeList_SelectedDataItemsChanged(IReadOnlyList<object> newSelection) {
TreeList.RefreshSummary();
}
}
If you implement a custom summary with a value that can change dynamically, call the RefreshSummary() method to update the TreeList’s summary values.
TreeList.RefreshSummary();
The TreeList component implements methods that obtain 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 TreeList component.
<h3>Total Sales: @SummaryText</h3>
<DxTreeList @ref="TreeList"
Data="Data"
KeyFieldName="ID"
ParentKeyFieldName="RegionID"
ShowAllRows="true">
<Columns>
<DxTreeListDataColumn FieldName="Region" />
<DxTreeListDataColumn FieldName="MarchSales" DisplayFormat="c0" />
<DxTreeListDataColumn FieldName="MarchChange" DisplayFormat="p2" />
<DxTreeListDataColumn FieldName="MarketShare" DisplayFormat="p0" />
</Columns>
<TotalSummary>
<DxTreeListSummaryItem SummaryType="TreeListSummaryItemType.Sum" FieldName="MarchSales" Visible="false" />
</TotalSummary>
</DxTreeList>
@code {
ITreeList TreeList { get; set; }
object Data { get; set; }
string SummaryText;
protected override void OnInitialized() {
Data = SalesByRegionDataProvider.GenerateData();
}
protected override void OnAfterRender(bool firstRender) {
if(firstRender) {
SummaryText = TreeList.GetTotalSummaryFormattedValue(TreeList.GetTotalSummaryItems()[0]);
StateHasChanged();
}
}
}