Skip to main content

GridCustomDataSourceItemsOptions Class

Namespace: DevExpress.Blazor

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

NuGet Package: DevExpress.Blazor

Declaration

public class GridCustomDataSourceItemsOptions :
    GridCustomDataSourceOptions

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

        if (options.Count >= 0) {
            return await ApplySorting(options, filteredQuery)
                .Skip(options.StartIndex)
                .Take(options.Count)
                .ToListAsync(cancellationToken);
        }

        return await ApplySorting(options, filteredQuery).ToListAsync(cancellationToken);
    }
    // ...
    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<Order> ApplySorting(GridCustomDataSourceItemsOptions options, IQueryable<Order> queryableSource) {
        if (options.SortInfo != null) {
            foreach (var sortInfo in options.SortInfo) {
                queryableSource = SortByField(sortInfo.FieldName, sortInfo.DescendingSortOrder, queryableSource);
            }
        }

        return queryableSource;
    }

    private static IQueryable<Order> SortByField(string fieldName, bool descendingOrder, IQueryable<Order> queryableSource) {
        var lambda = GetTypedLambda(fieldName);
        if (queryableSource.Expression.Type != typeof(IOrderedQueryable<Order>)) {
            return !descendingOrder
                ? queryableSource.OrderBy(lambda)
                : queryableSource.OrderByDescending(lambda);
        }

        return !descendingOrder
            ? ((IOrderedQueryable<Order>)queryableSource).ThenBy(lambda)
            : ((IOrderedQueryable<Order>)queryableSource).ThenByDescending(lambda);
    }

    private static Expression<Func<Order, object>> GetTypedLambda(string fieldName) {
        var parameter = Expression.Parameter(typeof(Order));
        var property = Expression.Property(parameter, fieldName);
        var lambda = Expression.Lambda<Func<Order, object>>(Expression.Convert(property, typeof(object)), parameter);
        return lambda;
    }
    // ...
    public void Dispose() {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    protected virtual void Dispose(bool disposing) {
        if (!_disposed) {
            if (disposing) {
                _context?.Dispose();
            }
            _disposed = true;
        }
    }
    // ...
}

Inheritance

Object
GridCustomDataSourceOptions
GridCustomDataSourceItemsOptions
See Also