DataGrid - wrong sortings in LoadDataArgs after loading saved settings

Here is my code below to reproduce - very simplified version of this one - DataGrid with custom sample of very simplified data, but without autosaving settings (only on demand through hitting the button) and serializing them.

Steps to reproduce - watch the parameter "args" of the LoadData method:

  1. Run the code
  2. Sort the list by Val2 - args.OrderBy: "Val2 asc"
  3. Save settings (hit the "SaveSettings" button) - args.OrderBy: "Val2 asc"
  4. Sort list by Val1 - args.OrderBy: "Val1 asc"
  5. Load settings saved before (hit the "LoadSettings" button) - args.OrderBy: "Val1 desc,Val2 asc" but must be "Val2 asc"

Interestingly, that Val1 sorting changed its value from "asc" to "desc" by itself - there are no steps in my actions where I set any sortings to "decs".

@using Radzen
@using System.Linq.Dynamic.Core
@page "/"

<RadzenButton Click="@Save" Text="SaveSettings" />
<RadzenButton Click="@Load" Text="LoadSettings" />

<RadzenDataGrid @bind-Settings="@Settings"
                AllowSorting="true"
                Data="@employees"
                TItem="Employee"
                Count="@count"
                LoadData="@LoadData"
                Style="height:400px">
    <Columns>
        <RadzenDataGridColumn TItem="Employee" Property="Val1" Title="Val1" />
        <RadzenDataGridColumn TItem="Employee" Property="Val2" Title="Val2" />
    </Columns>
</RadzenDataGrid>

@code {
    public class Employee
    {
        public int Val1 { get; set; }
        public int Val2 { get; set; }
    }

    List<Employee> source;
    IEnumerable<Employee> employees;
    int count;

    DataGridSettings settings;
    public DataGridSettings Settings
    {
        get => settings;
        set
        {
            if (settings != value)
                settings = value;
        }
    }

    DataGridSettings cachedSettings;

    protected override async Task OnInitializedAsync()
    {
        await base.OnInitializedAsync();

        source = new List<Employee>()
        {
            new Employee() { Val1 = 0, Val2 = 20 },
            new Employee() { Val1 = 1, Val2 = 10 },
            new Employee() { Val1 = 2, Val2 = 50 },
            new Employee() { Val1 = 3, Val2 = 80 },
            new Employee() { Val1 = 4, Val2 = 30 },
        };
    }

    protected void LoadData(LoadDataArgs args)
    {
        var query = source.AsQueryable();

        if (!string.IsNullOrEmpty(args.OrderBy))
            query = query.OrderBy(args.OrderBy);
        
        employees = query.ToList();
        count = employees.Count();
    }

    async Task Save()
    {
        await Task.CompletedTask;
        cachedSettings = Settings;
    }

    async Task Load()
    {
        await Task.CompletedTask;
        Settings = cachedSettings;
    }
}

You can call Reload() for the DataGrid to avoid this:


datagrid-loaddata-settings (2)

But it must be args.OrderBy: "Val2 asc".

I checked it in debug mode - after pressing the "LoadSettings" button the Load method is performed (now with your correction "grid.Reload()"), and bound Settings property sets its order as "Val2 asc, Val1 - null". That is right. But then the LoadData handler is called and the LoadDataArgs contain the wrong orderings "Val1 asc, Val2 - null". It seems like LoadSettings and LoadDataArgs objects become wrongly synchronized after loading new settings to the data grid.

Should LoadDataArgs and DataGridSettings contain almost the same filtering data (no matter that now it is a little bugged)? I mean, I can avoid the using of LoadDataArgs if it has an issue now, and rely only on DataGridSettings. I construct queries without dynamic LINQ, so I just parse DataGridSettings or LoadDataArgs fetching data from them. If DataGridSettings works well for now, I can perhaps renounce the using of LoadDataArgs and just fill the data grid source inside LoadData handler manually.

The second issue I've found lays in saving and loading sortings - the order of sortings is not preserved also. And this is by design, as far as I understood - Radzen saves in DataGridColumnSettings and SortDescriptor types only sort type (ascending, descending) for a column, but not an order of sortings. This is really important, because there are constructions in SQL like "order by columnName1 asc, columnName2 desc", and if I want to sort by columnName2 for the first and then by columnName1 for the second, then I want this should be restored after loading settings.

I have modified my code a little to allow multiple orders and also have changed test values.

@using Radzen
@using System.Linq.Dynamic.Core
@page "/"

<RadzenButton Click="@Save" Text="SaveSettings" />
<RadzenButton Click="@Load" Text="LoadSettings" />

<RadzenDataGrid @bind-Settings="@Settings"
                AllowSorting="true"
                Data="@employees"
                TItem="Employee"
                Count="@count"
                LoadData="@LoadData"
                AllowMultipleColumnSorting="true"
                ShowMultiColumnSortingIndex="true"
                Style="height:400px">
    <Columns>
        <RadzenDataGridColumn TItem="Employee" Property="Val1" Title="Val1" />
        <RadzenDataGridColumn TItem="Employee" Property="Val2" Title="Val2" />
    </Columns>
</RadzenDataGrid>

@code {
    public class Employee
    {
        public int Val1 { get; set; }
        public int Val2 { get; set; }
    }

    List<Employee> source;
    IEnumerable<Employee> employees;
    int count;

    DataGridSettings settings;
    public DataGridSettings Settings
    {
        get => settings;
        set
        {
            if (settings != value)
                settings = value;
        }
    }

    DataGridSettings cachedSettings;

    protected override async Task OnInitializedAsync()
    {
        await base.OnInitializedAsync();

        source = new List<Employee>()
        {
            new Employee() { Val1 = 0, Val2 = 30 },
            new Employee() { Val1 = 1, Val2 = 20 },
            new Employee() { Val1 = 2, Val2 = 80 },
            new Employee() { Val1 = 3, Val2 = 80 },
            new Employee() { Val1 = 4, Val2 = 20 },
        };
    }

    protected void LoadData(LoadDataArgs args)
    {
        var query = source.AsQueryable();

        if (!string.IsNullOrEmpty(args.OrderBy))
            query = query.OrderBy(args.OrderBy);
        
        employees = query.ToList();
        count = employees.Count();
    }

    async Task Save()
    {
        await Task.CompletedTask;
        cachedSettings = Settings;
    }

    async Task Load()
    {
        await Task.CompletedTask;
        Settings = cachedSettings;
    }
}

Now try to sort, for example, the second column descending and then the first column ascending:

image

Then save grid settings. Then remove all sortings and try to load previous settings. I get the following:

image

Interesting, that if after saving settings you remove only sorting for the first column, but not for the second one, then loading of settings is going right.

Another interesting thing - if after saving settings you remove only sorting for the second column, but for the first column make it descending, then loading the settings leads you to the following result:

image

The sortings are right, but the sign for the sorting for the first column looks like dash.

For me saving and loading sortings in data grid looks bugged and behaves unpredictable.

As for me, it will be better if a sort order will be added as additional parameter to DataGridColumnSettings and SortDescriptor. Perhaps it can be named "SortOrderIndex". It can help to solve the issue with incorrect sortings data in LoadDataArgs type also.

You can try the approach I've used in this post where data are loaded similar to your case after the page is already rendered:

(Instead of "DataGridColumnSettings" read it as "DataGridSettings" in my previous posts.)

No, this doesn't help. The main change is the OnAfterRenderAsync method that just saves grid settings at every change in these settings, except the first loading of the page where it tries to load them. But the idea is - to save and load only on demand, when the user clicks on a button.

As the author of that thread described, he ran into the same issue as me - he sorted a column, then the second one that comes before the first one - so the order of sortings is opposite as the order of columns. And after trying to load these sortings he get them in the same order as the columns, not opposite as these sortings were set.

And that is clear, because Radzen preserves no order of sortings in the DataGridSettings - the sortings are saved in the DataGridSettings.Columns.DataGridColumnSettings.SortOrder in the same order as columns. Radzen preserves it only in the LoadDataArgs.OrderBy as the whole sorting string, or in the LoadDataArgs.Sorts collection of SortDescriptor objects, which are stored inside this collection in the same order as they are obtained from the user when he or she makes these sortings in the UI.

The solution can be somehow simple, as for me - put a copy of these LoadDataArgs.OrderBy or LoadDataArgs.Sorts into the DataGridSettings. But it is only to save the right sortings order. To load and to restore them in the UI - another task. And Radzen clearly has a bug here.

In other words, Radzen sortings work perfectly only when you make just queries - change something in the filters or sort the columns - the LoadDataArgs with the right sortings order comes in this situation through the LoadData handler. But at saving and loading these changes Radzen uses DataGridSettings where no sortings order is saved.

As a temporary solution I have to implement my own component to store the sortings separately, to show them to the user and to restore their settings after loading them. DataGrid will be used with sortings disabled. And to collect the right sortings order to save them I need to combine the data from LoadDataArgs and DataGridSettings at every save. It looks like scrutches, but I hope Radzen team will fix the described bug soon.

1 Like