Currently, I'm working on the Radzen DataGrid and trying to make the "bind-settings" feature work. This feature should make it easier to save and load the settings of the datagrid. I followed the steps from the official website to set it up, and you can find the link here: Data Grid Save Setting.
However, I'm facing a problem where applying filters to the columns in the grid doesn't always work as expected. Sometimes it works fine, but other times the code gets stuck in a loop that involves the "OnLoad" and "OnAfterRenderAsync" methods. This makes the grid freeze, and I have to close the application manually. Unfortunately, I can't figure out a consistent way to recreate this problem. It can happen when I first apply a filter or after applying multiple filters to the grid.
I can't share the whole project, but I've included the Razor and C# files for you to review. I've also looked for solutions in discussions about similar issues, but I haven't found a solution that fits my problem. I'm hopeful that you could take a look at what I've done so far and help me find out what's causing this issue.
I really appreciate any help you can give me. Thank you in advance!
using Microsoft.JSInterop;
using Radzen;
using Radzen.Blazor;
using System.Text.Json;
namespace Agri.Proc.Cat.Web.Pages
{
public partial class GridSettingTest
{
RadzenDataGrid<ContractDto> grid;
IEnumerable<ContractDto> contracts;
protected ContractsSearchCriteriaDto SearchCriteria = new();
int count;
bool isLoading = false;
bool loaded;
async Task LoadData(LoadDataArgs args)
{
isLoading = true;
await Task.Yield();
SearchCriteria.CreatedDateFrom = DateTime.Today.AddDays(-30);
SearchCriteria.CreatedDateTo = DateTime.Today;
SearchCriteria.OrderBy = "Id desc";
SearchCriteria.Take = 25;
SearchCriteria.FilterBy = args.Filter;
var searchCriteriaJson = SerializeUtil.Serialize(SearchCriteria);
// Simulate async data loading
await Task.Delay(2000);
var contractsResult = await APIClient.PostAsync<CountableDto<List<ContractDto>>>(Constants.API_CONTRACT_GETCONTRACTSBYSEARCH, searchCriteriaJson);
if (!contractsResult.Success)
{
contracts = new List<ContractDto>();
}
else
{
contracts = contractsResult.Value.Value;
}
isLoading = false;
loaded = true;
}
DataGridSettings _settings;
public DataGridSettings Settings
{
get
{
return _settings;
}
set
{
if (_settings != value)
{
_settings = value;
InvokeAsync(SaveStateAsync);
}
}
}
private async Task LoadStateAsync()
{
var result = await JSRuntime.InvokeAsync<string>("window.localStorage.getItem", "SettingsLoadData");
if (!string.IsNullOrEmpty(result))
{
_settings = JsonSerializer.Deserialize<DataGridSettings>(result);
}
}
private async Task SaveStateAsync()
{
await JSRuntime.InvokeVoidAsync("eval", $@"window.localStorage.setItem('SettingsLoadData', '{JsonSerializer.Serialize<DataGridSettings>(Settings)}')");
}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender || loaded)
{
await LoadStateAsync();
if (loaded)
{
loaded = false;
await Task.Yield();
await grid.Reload();
loaded = false;
}
}
}
}
}
@using Radzen
@using Microsoft.EntityFrameworkCore
@using Microsoft.JSInterop
@using System.Text.Json
@using System.Linq.Dynamic.Core
<RadzenContent Container="main">
<ChildContent>
<p>This example shows how to save/load DataGrid state using Settings property when binding using LoadData event.</p>
<p>The state includes current page index, page size, groups and columns filter, sort, order, width and visibility.</p>
<RadzenButton Click="@(args => Settings = null)" Text="Clear saved settings" Style="margin-bottom: 16px" />
<RadzenButton Click="@(args => NavigationManager.NavigateTo("/datagrid-save-settings", true))" Text="Reload" Style="margin-bottom: 16px" />
<RadzenDataGrid @ref=grid @bind-Settings="@Settings" AllowFiltering="true" AllowColumnPicking="true" AllowGrouping="true" AllowPaging="true" PageSize="4"
AllowSorting="true" AllowMultiColumnSorting="true" ShowMultiColumnSortingIndex="true"
AllowColumnResize="true" AllowColumnReorder="true" ColumnWidth="200px"
FilterPopupRenderMode="PopupRenderMode.OnDemand" FilterCaseSensitivity="FilterCaseSensitivity.CaseInsensitive"
Data="@contracts" IsLoading=@isLoading Count="@count" LoadData=@LoadData TItem="ContractDto">
<Columns>
<RadzenDataGridColumn TItem="ContractDto" Property="@($"{nameof(ContractDto.ContractType)}.{nameof(ContractTypeDto.DisplayName)}")" Title="Type" Width="80px" FilterOperator="FilterOperator.Equals" />
<RadzenDataGridColumn TItem="ContractDto" Property="@(nameof(ContractDto.Id))" SortProperty="@(nameof(ContractDto.Id))" SortOrder="SortOrder.Descending" Title="Id" Width="85px" />
<RadzenDataGridColumn TItem="ContractDto" Property="@(nameof(ContractDto.OutsideRefNumber))" Title="Outside Ref #" Width="150px" />
<RadzenDataGridColumn TItem="ContractDto" Property="@($"{nameof(ContractDto.Payee)}.{nameof(VendorDto.IdAndName)}")" Title="Payee" Width="250px" FilterProperty="Payee.Name" SortProperty="Payee.Name" />
<RadzenDataGridColumn TItem="ContractDto" Property="@(nameof(ContractDto.HeadCount))" Title="#HD" Width="85px" Filterable="false" Sortable="false" />
<RadzenDataGridColumn TItem="ContractDto" Property="@($"{nameof(ContractDto.Status)}.{nameof(ContractStatusDto.DisplayName)}")" Title="Status" Width="115px" FilterOperator="FilterOperator.Equals" />
</Columns>
</RadzenDataGrid>
</ChildContent>
</RadzenContent>