Skip to main content
All docs
V26.1
  • GridCustomDataSourceTotalSummaryOptions.SummaryInfo Property

    Returns a list of objects that contain information about a total summary to be calculated.

    Namespace: DevExpress.Blazor

    Assembly: DevExpress.Blazor.Grid.v26.1.dll

    NuGet Package: DevExpress.Blazor

    Declaration

    public IReadOnlyList<GridCustomDataSourceSummaryInfo> SummaryInfo { get; }

    Property Value

    Type Description
    IReadOnlyList<GridCustomDataSourceSummaryInfo>

    A list of GridCustomDataSourceSummaryInfo objects.

    Remarks

    If standard data binding modes do not meet specific business requirements, you can implement your own data provider. To do so, create a GridCustomDataSource descendant and assign it to the Grid or TreeList component’s Data property.

    The following code snippet implements a custom data provider’s GetTotalSummaryAsync method:

    View Example: Custom Data Source Binding using Entity Framework Core

    using DevExpress.Blazor;
    using DevExpress.Data.Filtering;
    using DevExpress.Data.Filtering.Helpers;
    using CustomDataSource.Models;
    using System.Collections;
    using System.Linq.Expressions;
    using DevExpress.Data.Linq;
    using DevExpress.Data.Linq.Helpers;
    using Microsoft.EntityFrameworkCore;
    
    namespace CustomDataSource.Services;
    
    public class OrdersDataSource : GridCustomDataSource, IDisposable {
        protected override Type DataItemType => typeof(Order);
        private readonly NorthwindContext _context;
        private bool _disposed = false;
    
        public OrdersDataSource(IDbContextFactory<NorthwindContext> contextFactory) {
            _context = contextFactory.CreateDbContext();
        } 
        // ...
        public override async Task<IList> GetTotalSummaryAsync(GridCustomDataSourceTotalSummaryOptions options, CancellationToken cancellationToken) {
            var filteredQuery = ApplyFiltering(options.FilterCriteria, _context.Orders);
    
            var summaryQuery = GetGroupByAndSelectQuery(options.SummaryInfo, filteredQuery, true);
            var result = await summaryQuery.FirstOrDefaultAsync(cancellationToken);
            return result != null
                ? result
                    .Select(d => d.Value)
                    .ToList()
                : null;
        }
        // ...
        private static IQueryable<Order> ApplyFiltering(CriteriaOperator criteria, IQueryable<Order> queryableSource) {
            return !criteria.ReferenceEqualsNull()
                ? (IQueryable<Order>)queryableSource.AppendWhere(
                    new CriteriaToEFExpressionConverter(queryableSource.Provider.GetType()), criteria)
                : queryableSource;
        }
        // ...
        private static IQueryable<Dictionary<string, object>> GetGroupByAndSelectQuery(IReadOnlyList<GridCustomDataSourceSummaryInfo> summaryInfoList,
            IQueryable<Order> queryableSource, bool totalSummary, string groupedFieldName = "") {
            IQueryable groupedQuery;
            Type groupedPropertyType;
            if (totalSummary) {
                groupedPropertyType = typeof(int);
                groupedQuery = queryableSource.GroupBy(x => 1);
            } else {
                var parameter = Expression.Parameter(typeof(Order));
                var property = Expression.Property(parameter, groupedFieldName);
                groupedPropertyType = property.Type;
                var groupLambda = Expression.Lambda(property, parameter);
    
                var groupByCall = Expression.Call(typeof(Queryable), "GroupBy", new[] { typeof(Order), groupedPropertyType },
                    queryableSource.Expression, groupLambda);
                groupedQuery = queryableSource.Provider.CreateQuery(groupByCall);
            }
    
            var groupType = typeof(IGrouping<,>).MakeGenericType(groupedPropertyType, typeof(Order));
            var group = Expression.Parameter(groupType);
    
            // defining a dictionary that will hold group info
            var dictItems = new List<ElementInit>();
            var addMethod = typeof(Dictionary<string, object>).GetMethod("Add");
            if (!totalSummary) {
                dictItems.AddRange(new List<ElementInit> {
                    Expression.ElementInit(addMethod, Expression.Constant("Value"),
                        Expression.Convert(Expression.Property(group, "Key"), typeof(object))
                    ),
                    Expression.ElementInit(addMethod, Expression.Constant("DataItemCount"),
                        Expression.Convert(Expression.Call(typeof(Enumerable), "Count",
                            new[] { typeof(Order) }, group), typeof(object))
                    )
                });
            }
    
            for (int i = 0; i < summaryInfoList.Count; i++) {
                var summaryInfo = summaryInfoList[i];
    
                var groupSummaryCall = GetGroupSummaryCall(summaryInfo, group);
                dictItems.Add(Expression.ElementInit(addMethod, Expression.Constant("Summary_" + i),
                    Expression.Convert(groupSummaryCall, typeof(object))));
            }
    
            var dictInit = Expression.ListInit(Expression.New(typeof(Dictionary<string, object>)), dictItems);
    
            // creating the select query
            Type selectFuncType = typeof(Func<,>).MakeGenericType(groupType, typeof(Dictionary<string, object>));
            var selectLambda = Expression.Lambda(selectFuncType, dictInit, group);
            var selectCall = Expression.Call(typeof(Queryable), "Select",
                new[] { groupedQuery.ElementType, typeof(Dictionary<string, object>) },
                groupedQuery.Expression, selectLambda);
    
            return groupedQuery.Provider.CreateQuery<Dictionary<string, object>>(selectCall);
        }
    
        private static Expression GetGroupSummaryCall(GridCustomDataSourceSummaryInfo summaryInfo,
            Expression group) {
            var parameter = Expression.Parameter(typeof(Order));
            var property = Expression.Property(parameter, summaryInfo.FieldName);
            var summaryLambda = Expression.Lambda(property, parameter);
    
            switch (summaryInfo.SummaryType) {
                case GridSummaryItemType.Avg:
                    return Expression.Call(typeof(Enumerable), "Average", new[] { typeof(Order) },
                        group, summaryLambda);
                case GridSummaryItemType.Count:
                    return Expression.Call(typeof(Enumerable), "Count", new[] { typeof(Order) },
                        group);
                case GridSummaryItemType.Max:
                    return Expression.Call(typeof(Enumerable), "Max", new[] { typeof(Order), property.Type },
                        group, summaryLambda);
                case GridSummaryItemType.Min:
                    return Expression.Call(typeof(Enumerable), "Min", new[] { typeof(Order), property.Type },
                        group, summaryLambda);
                case GridSummaryItemType.Sum:
                    return Expression.Call(typeof(Enumerable), "Sum", new[] { typeof(Order) },
                        group, summaryLambda);
                default:
                    throw new NotSupportedException(summaryInfo.SummaryType.ToString());
            }
        }
        // ...
        public void Dispose() {
            Dispose(true);
            GC.SuppressFinalize(this);
        }
    
        protected virtual void Dispose(bool disposing) {
            if (!_disposed) {
                if (disposing) {
                    _context?.Dispose();
                }
                _disposed = true;
            }
        }
        // ...
    }
    

    The following code snippet (auto-collected from DevExpress Examples) contains a reference to the SummaryInfo property.

    Note

    The algorithm used to collect these code examples remains a work in progress. Accordingly, the links and snippets below may produce inaccurate results. If you encounter an issue with code examples below, please use the feedback form on this page to report the issue.

    See Also