Hi i'm on the way to encapsulate RadzenDataGrid to be used with generic entity. It actually works to populate the grid with dynamic columns creation and upadting rows using callback. but i failed to make builtin filters work. the LoadDataArgs args.Filter is always empty ... To clarified i use ExpandObject as datastructure for my data, perhaps it may hurt the filtering logic, but for me it not explained why args are not correclty sets when call to loadData fired. Somebody could clarify this point for me ?
Regards
excerpt from my implementation :
In razor page
@inject ILogger<DynamicPageRadzen> Log
@inject GenericDataService<Programmation> DataService
<h3>generic entity with RadzenDataGrid Dynamic</h3>
<DynamicRadzenDataGrid Items="pageData" ItemsCount="totalRecords" ItemsPerPage="@itemsPerPage" OnSaveItem="HandleSaveAsync" OnLoadData="LoadData" />
@code {
private List<ExpandoObject>? pageData;
private int totalRecords;
private string pageName = "test-dynamic-radzen";
private int itemsPerPage = 10;
protected override async Task OnInitializedAsync()
{
var data = await DataService.GetTopAsync(itemsPerPage);
pageData = data.Select(I => ExpandoHelper.ToExpando(I)).ToList();
totalRecords = await DataService.GetCountAsync();
}
private async Task<List<ExpandoObject>?> LoadData(LoadDataArgs args)
{
try
{
var query = DataService.Query();
if (!string.IsNullOrWhiteSpace(args.Filter))
{
query = query.Where(args.Filter); // filter using System.Linq.Dynamic.Core
}
else
{
Log.LogInformation($"In {pageName} LoadData, args.Filter is null or Empty");
}
In my DynamicRadzenDatagrid component
@using System.Dynamic
@using Radzen
@using Radzen.Blazor
<style>
.rz-grid-table {
width: unset;
}
</style>
@if (Items != null && Items.Any())
{
var firstItem = (IDictionary<string, object?>)Items.First();
<RadzenDataGrid @ref="grid"
Data="@Items"
TItem="ExpandoObject"
EditMode="DataGridEditMode.Single"
AllowFiltering="true"
AllowSorting="true"
AllowPaging="true"
FilterMode="FilterMode.Advanced"
PageSize="@ItemsPerPage"
Count="@ItemsCount"
LoadData="@LoadData"
RowUpdate="@OnUpdateRow"
GridLines="@GridLines"
Density="@Density"
ColumnWidth="200px">
<Columns>
@foreach (var key in firstItem.Keys)
{
<RadzenDataGridColumn TItem="ExpandoObject" Property="@key" Title="@key">
<Template Context="data">
@{
var dict = (IDictionary<string, object?>)data;
var value = dict[key];
@value
}
</Template>
<EditTemplate Context="data">
@{
var dict = (IDictionary<string, object?>)data;
var currentValue = dict[key];
var valueType = currentValue?.GetType();
if (valueType == typeof(bool))
{
bool val = currentValue as bool? ?? false;
<RadzenCheckBox TValue="bool"
Value="@val"
ValueChanged="@(v => dict[key] = v)" />
}
else if (valueType == typeof(DateTime))
{
DateTime val = currentValue as DateTime? ?? DateTime.MinValue;
<RadzenDatePicker TValue="DateTime"
Value="@val"
ValueChanged="@(v => dict[key] = v)"
Style="width:100%" />
}
else if (valueType == typeof(int))
{
int val = currentValue as int? ?? 0;
<RadzenNumeric TValue="int"
Value="@val"
ValueChanged="@(v => dict[key] = v)"
Style="width:100%" />
}
else if (valueType == typeof(double))
{
double val = currentValue as double? ?? 0;
<RadzenNumeric TValue="double"
Value="@val"
ValueChanged="@(v => dict[key] = v)"
Style="width:100%" />
}
else
{
string val = currentValue?.ToString() ?? string.Empty;
<RadzenTextBox Value="@val"
ValueChanged="@(v => dict[key] = v)"
Style="width:100%" />
}
}
</EditTemplate>
</RadzenDataGridColumn>
}
<RadzenDataGridColumn TItem="ExpandoObject" Filterable="false" Sortable="false" TextAlign="TextAlign.Right" Width="150px" Frozen="true" FrozenPosition="FrozenColumnPosition.Right">
<Template Context="data">
<RadzenButton Icon="edit"
ButtonStyle="ButtonStyle.Primary"
Size="ButtonSize.Small"
Click="@(() => grid.EditRow(data))" />
</Template>
<EditTemplate Context="data">
<RadzenButton Icon="save"
ButtonStyle="ButtonStyle.Success"
Size="ButtonSize.Small"
Click="@(() => grid.UpdateRow(data))" />
<RadzenButton Icon="cancel"
ButtonStyle="ButtonStyle.Light"
Size="ButtonSize.Small"
Click="@(() => grid.CancelEditRow(data))" />
</EditTemplate>
</RadzenDataGridColumn>
</Columns>
</RadzenDataGrid>
}
else
{
<p><em>No Data to display.</em></p>
}
@code {
[Parameter] public List<ExpandoObject>? Items { get; set; }
[Parameter] public int ItemsCount { get; set; }
[Parameter] public int ItemsPerPage { get; set; }
[Parameter] public EventCallback<ExpandoObject> OnSaveItem { get; set; }
[Parameter] public Func<LoadDataArgs, Task<List<ExpandoObject>>>? OnLoadData { get; set; }
Density Density = Density.Compact;
Radzen.DataGridGridLines GridLines = Radzen.DataGridGridLines.Both;
private RadzenDataGrid<ExpandoObject>? grid;
private async Task LoadData(LoadDataArgs args)
{
if (OnLoadData is not null)
{
Items = await OnLoadData(args);
}
StateHasChanged();
}
private async Task OnUpdateRow(ExpandoObject item)
{
if (OnSaveItem.HasDelegate)
{
await OnSaveItem.InvokeAsync(item);
}
}
}
Log on execution
2025-06-02 09:25:13.080 +02:00 [INF] In test-dynamique-radzen LoadData, args.Filter is null or Empty
Hello Enchev,
Thanks for answering.
Ok! i've used this example first in my test but could you confirm that the type of TiTem is the problem? if so why or anything else in my approch? Regards
Hi Enchev, I duplicated your demo and simply added my private async Task LoadData(LoadDataArgs args) method to retrieve data from my DBMS backend. I think the problem I'm having with ExpandoObject List also occurs if I don't use IEnumerable<MyEntity> to populate the data grid...
I've set up two pages with RadzenDataGrid. The first, let's say entirely static, uses IEnumerable<MyEntity>. Everything works fine, and when loaddata is called, here's the debug view of args.Filter passed to LoadData.
When I try a "dynamic version", second page, with your demo code and use IEnumerable<IDictionary<string, object>> to populate the RadzenDataGrid, the args.Filter content is different, as you can see, and throws an exception (previously incorrectly caught) when using System.Linq.Dynamic.Core.
if (!string.IsNullOrWhiteSpace(args.Filter)) { query = query.Where(args.Filter); }
Here is a code snippet heavily inspired by your demos that exposes my problem. I hope it will be easily adaptable to your test environment. The Exception show off on Console Log.
No problem I will try to do so ! But what do you need or wich part of this code is a problem for you ?
FYI, for me, this trick permit to focus more precisly the problem ! a corected filter works ! but there is also the same formatting problem for args.OrderBy !
hum i dont think so; beware that it is data that is bind to the grid not employees ...
You could see that data load well on the online demo page, filter raise exception but works after correction, and order raise only exception !
I'm sorry, but you lost me
I understood that to be able to manage the datagrid in dynamic mode, you had to use a dictionary structure. Using the code in your demo, this is the case. I don't see any other way to link to the database data other than converting the data returned by the queries into a dictionary to refresh the variable linked to the datagrid, with the need to convert the data once the database access is complete! Would you be kind enough to tell me how to do it differently, or if there is a demo that addresses this particular case, which complements your generic Dadagrid demo.
Well, I don’t think I can add anything to what I already said and I don’t have any spare time to argue with you for obvious things. I’’m closing this thread.