Skip to main content

GridCustomDataSourceSummaryInfo.FieldName Property

Specifies a data source field for which a summary is calculated.

Namespace: DevExpress.Blazor

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

NuGet Package: DevExpress.Blazor

Declaration

public string FieldName { get; }

Property Value

Type Description
String

The field name.

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 GetGroupInfoAsync 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<GridCustomDataSourceGroupInfo>> GetGroupInfoAsync(GridCustomDataSourceGroupingOptions options,
        CancellationToken cancellationToken) {
        var filteredQuery = ApplyFiltering(options.FilterCriteria, _context.Orders);

        var summaryQuery = GetGroupByAndSelectQuery(options.SummaryInfo, filteredQuery, false, options.FieldName);
        var resultList = await summaryQuery.ToListAsync(cancellationToken);

        var groupInfoList = new List<GridCustomDataSourceGroupInfo>();
        foreach (var result in resultList) {
            var groupInfo = new GridCustomDataSourceGroupInfo() { Value = result["Value"], DataItemCount = (int)result["DataItemCount"] };

            var summaryList = new List<object>();
            foreach (var kvp in result) {
                if (kvp.Key.StartsWith("Summary_")) {
                    summaryList.Add(kvp.Value);
                }
            }

            groupInfo.SummaryValues = summaryList;
            groupInfoList.Add(groupInfo);
        }

        return options.DescendingSortOrder
            ? groupInfoList
                .OrderByDescending(g => g.Value)
                .ToList()
            : groupInfoList
                .OrderBy(g => g.Value)
                .ToList();
    }
    // ...
    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 FieldName 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