Skip to main content

GridCustomDataSource Class

Allows you to bind DxGrid and DxTreeList to a custom data source.

Namespace: DevExpress.Blazor

Assembly: DevExpress.Blazor.v24.1.dll

NuGet Package: DevExpress.Blazor

Declaration

public abstract class GridCustomDataSource

Remarks

You can bind the Grid to data in the following ways:

The TreeList component supports the following data binding scenarios:

We recommend using the GridCustomDataSource class only if the methods described are unsuitable.

The following code snippet implements a custom data source based on the GridCustomDataSource class:

View Example: Bind the Grid to OData Data Source

using System.Collections;
using Blazor.WebAssembly.Models;
using DevExpress.Blazor;
using DevExpress.Data.Filtering;
using DevExpress.Data.Filtering.Helpers;
using Simple.OData.Client;

namespace Blazor.WebAssembly.Services;

public class SimpleODataClientDataSource : GridCustomDataSource {
    private readonly ODataClient _client;
    public SimpleODataClientDataSource(IHttpClientFactory httpClientFactory)
        => _client = new ODataClient(new ODataClientSettings(httpClientFactory.CreateClient("API"), new Uri("odata/", UriKind.Relative)));

    public override async Task<int> GetItemCountAsync(GridCustomDataSourceCountOptions options, CancellationToken cancellationToken)
        => await ApplyFiltering(options.FilterCriteria, _client.For<Post>()).Count()
            .FindScalarAsync<int>(cancellationToken);

    public override async Task<IList> GetItemsAsync(GridCustomDataSourceItemsOptions options, CancellationToken cancellationToken) {
        var filteredClient = ApplyFiltering(options.FilterCriteria, _client.For<Post>().Top(options.Count).Skip(options.StartIndex));
        return (await ApplySorting(options, filteredClient).FindEntriesAsync(cancellationToken)).ToList();
    }

    private static IBoundClient<Post> ApplyFiltering(CriteriaOperator criteria, IBoundClient<Post> boundClient)
        => !criteria.ReferenceEqualsNull() ? boundClient.Filter(ToSimpleClientCriteria(criteria)) : boundClient;

    private static string ToSimpleClientCriteria(CriteriaOperator criteria)
        => $"{criteria}".Replace("[", "").Replace("]", "");

    private static IBoundClient<Post> ApplySorting(GridCustomDataSourceItemsOptions options, IBoundClient<Post> boundClient) {
        return options.SortInfo != null && options.SortInfo.Any() ? boundClient.OrderBy(options.SortInfo
                .Where(info => !info.DescendingSortOrder).Select(info => info.FieldName).ToArray())
            .OrderByDescending(options.SortInfo
                .Where(info => info.DescendingSortOrder).Select(info => info.FieldName).ToArray()) : boundClient;
    }

    public async Task DeleteAsync(Post instance)
        => await _client.For<Post>().Key(instance.ID).DeleteEntryAsync();

    public async Task AddOrUpdateAsync(Post instance, bool update = false) {
        if (!update) {
            await _client.For<Post>().Set(new { instance.Title, instance.Content }).InsertEntryAsync();
        }
        else {

            await _client.For<Post>().Key(instance.ID).Set(instance).UpdateEntryAsync();
        }
    }
}

During initialization, a GridCustomDataSource descendant sends an additional request to determine the item type. If the item type differs from ExpandoObject, you can specify this type directly in the descendant configuration to avoid additional requests:

private class MyCustomDataSource<T> : GridCustomDataSource {
    protected override Type DataItemType => typeof(T)
    // ...
}

Inheritance

See Also