Bind Blazor Grid to Queryable Data Sources
- 8 minutes to read
You can use a GridDevExtremeDataSource<T> to bind the Blazor Grid component to a large IQueryable data collection. Data source implementation is based on the DevExpress DevExtreme.AspNet.Data library.
When bound to this data source, the Grid loads data on demand instead of the entire dataset. The component delegates all data shaping operations to the underlying query provider, such as LINQ to Objects, EF Core, and so on. These services process data more efficiently and improve overall performance.
Bind to Local Data
Follow the steps below to bind the Grid to a large IQueryable data collection stored locally:
- Create a GridDevExtremeDataSource class instance and pass your IQueryable data collection as the constructor parameter.
- Assign this instance to the Grid’s Data property.
The following code snippet uses the Entity Framework Core technology to bind the Grid to an IQueryable data collection:
@using Microsoft.EntityFrameworkCore
@inject IDbContextFactory<NorthwindContext> NorthwindContextFactory
@implements IDisposable
<DxGrid Data="GridDataSource">
<Columns>
<DxGridDataColumn FieldName="OrderDate" DisplayFormat="d" />
<DxGridDataColumn FieldName="CustomerName" />
<DxGridDataColumn FieldName="Country" />
<DxGridDataColumn FieldName="Freight" DisplayFormat="n2" />
<DxGridDataColumn FieldName="ExtendedPrice" DisplayFormat="c" />
</Columns>
</DxGrid>
@code {
object GridDataSource { get; set; }
NorthwindContext Northwind { get; set; }
protected override void OnInitialized() {
Northwind = NorthwindContextFactory.CreateDbContext();
GridDataSource = new GridDevExtremeDataSource<Invoice>(Northwind.Invoices);
}
public void Dispose() {
Northwind?.Dispose();
}
}

Bind to a Web API Service
Follow these steps to bind the Grid to a large IQueryable collection published as an HTTP service:
Create a GridDevExtremeDataSource class instance and pass two constructor parameters:
- An HttpClient object that sends HTTP requests and receives HTTP responses from the specified URL.
- A URL to the service’s controller action that processes HTTP requests (see step 3).
Assign the GridDevExtremeDataSource class instance to the Grid’s Data property.
- On the service side, implement an API controller and create action methods. Use the DevExtreme.AspNet.Data library’s DataSourceLoader class to create
LoadResultbased on load options. - Implement a custom model binder. Refer to the following link for additional information and an example: Server Side Configuration.
The following code sample binds the Grid to an IQueryable collection published as an HTTP service:
@inject HttpClient HttpClient
<DxGrid Data="@Data">
<Columns>
<DxGridDataColumn FieldName="CustomerID" />
<DxGridDataColumn FieldName="OrderDate" DisplayFormat="d" />
<DxGridDataColumn FieldName="Freight" DisplayFormat="n2" />
<DxGridDataColumn FieldName="ShipCountry" />
</Columns>
</DxGrid>
@code {
object Data { get; set; }
public class Order {
public string CustomerID { get; set; }
public DateTime OrderDate { get; set; }
public decimal Freight { get; set; }
public string ShipCountry { get; set; }
}
protected override async Task OnInitializedAsync() {
var uri = new Uri("https://js.devexpress.com/Demos/NetCore/api/DataGridWebApi/Orders");
Data = new GridDevExtremeDataSource<Order>(HttpClient, uri);
}
}

Custom HTTP Requests
You can also generate and send custom HTTP requests:
Implement an asynchronous function that returns a
Task<Stream>object and accepts two parameters:- A URL to the service’s controller action.
- A CancellationToken object that propagates a cancellation notification.
Create a GridDevExtremeDataSource class instance and pass two constructor parameters (the newly created function and the URL to the service’s controller action).
- Assign the GridDevExtremeDataSource instance to the Grid’s Data property.
The following code snippet adds an authorization header to HTTP requests. Note that you should process authorization information in the service’s controller.
@*...*@
@code {
// ...
protected override async Task OnInitializedAsync() {
var uri = new Uri("https://js.devexpress.com/Demos/NetCore/api/DataGridWebApi/Orders");
Data = new GridDevExtremeBasedDataSource<Order>(ExecuteDataSourceHttpRequest, url);
}
async Task<Stream> ExecuteDataSourceHttpRequest(Uri url, CancellationToken cancellationToken) {
using var request = new HttpRequestMessage(HttpMethod.Get, url);
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", "...");
var response = await HttpClient.SendAsync(request);
return await response.Content.ReadAsStreamAsync();
}
}
Limitations
Note the following Grid-related limitations when using GridDevExtremeDataSource:
- Cell editing is unavailable.
- Custom sorting is unavailable.
- Interval/custom grouping is unavailable.
- Search, filter, sorting, and grouping against display text are unavailable.
- Custom summary calculation is unavailable.
AllPagesmode of the Select All checkbox is unavailable.- Unbound columns are unavailable.
- Sorting, filtering, or data grouping during select/deselect all processing cancels the operation.
- Criteria operators applied by the SetFieldFilterCriteria/SetFilterCriteria method are limited. For additional information, see method descriptions.
- To call the SetFocusedDataItemAsync method, you must specify the KeyFieldName/KeyFieldNames property value.
- SelectAllAsync and DeselectAllAsync methods load all data and can impact overall performance and increase memory consumption.
- A second call to the SelectAllAsync/DeselectAllAsync method cancels the operation initiated by a previously called method.
The GridDevExtremeDataSource loads data asynchronously in small portions (instead of the entire dataset). To ensure correct data operations, you must:
- Call WaitForDataLoadAsync before methods that read Grid data (GetRowValue, GetTotalSummaryValue, and so on).
- Call WaitForRemoteSourceRowLoadAsync before methods that accept a row visible index as a parameter (SelectRow, StartEditRowAsync, and so on).