Here’s a controller to add dynamic summaries to XAF Blazor ListViews until DevExpress includes them in the context menu for the footer.
public class SummaryController : ViewController<ListView> { SingleChoiceAction summaryAction; public SummaryController() { summaryAction = new SingleChoiceAction(this, "summaryAction", PredefinedCategory.Edit); summaryAction.Caption = "Summary"; summaryAction.ItemType = SingleChoiceActionItemType.ItemIsOperation; summaryAction.Execute += SummaryAction_Execute; } protected override void OnActivated() { base.OnActivated(); summaryAction.Items.Clear(); var typ = ((TypeInfo)View.ObjectTypeInfo).Type; var properties = typ.GetProperties(); foreach (var prop in properties) { if (prop.Name == "Oid" | prop.Name == "This" | prop.Name == "Loading" | prop.Name == "ClassInfo" | prop.Name == "Session" | prop.Name == "IsLoading" | prop.Name == "IsDeleted") continue; var setPropiedadSummary = new ChoiceActionItem(typ.Name, prop.Name, null); summaryAction.Items.Add(setPropiedadSummary); AddSummary(setPropiedadSummary, typeof(GridSummaryItemType)); } summaryAction.Items.Add(new ChoiceActionItem("Remove", "Remove", null)); } void AddSummary(ChoiceActionItem parentItem, Type enumType) { EnumDescriptor ed = new EnumDescriptor(enumType); foreach (object current in ed.Values) { if(current.ToString() == "Custom" || current.ToString() == "None") { continue; } ChoiceActionItem item = new ChoiceActionItem(current.ToString(), current); parentItem.Items.Add(item); } } private void SummaryAction_Execute(object sender, SingleChoiceActionExecuteEventArgs e) { if (View.Editor is DxGridListEditor editor) { if (e.SelectedChoiceActionItem.Caption == "Remove") { editor.GridSummary.TotalSummary.Clear(); } else { DxGridSummaryItemWrapper summary = new DxGridSummaryItemWrapper(new DxGridSummaryItemModel { SummaryType = (GridSummaryItemType)e.SelectedChoiceActionItem.Data, FieldName = e.SelectedChoiceActionItem.ParentItem.Caption, FooterColumnName = e.SelectedChoiceActionItem.ParentItem.Caption }); if (!editor.GridSummary.TotalSummary.Any(s => s.SummaryType == ConvertSummaryItemType((GridSummaryItemType)e.SelectedChoiceActionItem.Data) & s.FieldName == e.SelectedChoiceActionItem.ParentItem.Caption)) { editor.GridSummary.TotalSummary.Add(summary); } } RefreshController refreshController = Frame.GetController<RefreshController>(); if (refreshController != null) { refreshController.RefreshAction.DoExecute(); } } } private DevExpress.Data.SummaryItemType ConvertSummaryItemType(GridSummaryItemType summaryItemType) { return summaryItemType switch { GridSummaryItemType.Sum => DevExpress.Data.SummaryItemType.Sum, GridSummaryItemType.Min => DevExpress.Data.SummaryItemType.Min, GridSummaryItemType.Max => DevExpress.Data.SummaryItemType.Max, GridSummaryItemType.Count => DevExpress.Data.SummaryItemType.Count, GridSummaryItemType.Avg => DevExpress.Data.SummaryItemType.Average, GridSummaryItemType.Custom => DevExpress.Data.SummaryItemType.Custom, _ => DevExpress.Data.SummaryItemType.None }; } protected override void OnViewControlsCreated() { base.OnViewControlsCreated(); // Access and customize the target View control. } protected override void OnDeactivated() { // Unsubscribe from previously subscribed events and release other references and resources. base.OnDeactivated(); } }
Video: