Custom Grouping Order in Grid for Blazor
Environment
| Product | Grid for Blazor |
Description
I want to group data programmatically in the Telerik Grid for Blazor by one column. The group order must match a specific sequence rather than the default ascending or descending order. I need to sort groups in a custom way, based on a predefined order of the data, or a custom pattern.
This KB article answers the following questions:
- How can I apply custom sorting to groups in the Grid for Blazor?
- What is the approach to sort Grid groups in a non-standard order?
- Can I define a custom sequence for grouped data in the Grid for Blazor?
Solution
To achieve custom grouping order in the Telerik Grid for Blazor, follow these steps:
-
Bind the Grid with the
OnReadevent to handle data operations manually. Refer to the official documentation forOnReadand Grouping withOnRead -
Instead of using the
ToDataSourceResult()method, group the data with custom code. Each group must be represented by anAggregateFunctionsGroupobject. To understand the Grid's expectations, inspect thedatasourceResultvariable structure and content with a debugger, as shown in Grouping withOnRead. -
Implement custom sorting logic for grouped data based on your specific order requirements (e.g., D, A, C, B) within the
OnReadmethod. -
To display multiple property names and values in group headers, consider using the
GroupHeaderTemplate. -
(Optionally) Disable the Grid's
Groupablesetting to hide the group panel if you want to prevent users from modifying the grouping state.
@using Telerik.Blazor.Components
@using System.Collections.ObjectModel
@using Telerik.DataSource.Extensions
@using Telerik.DataSource
<h1>Custom sort of grouping on a column</h1>
<TelerikGrid OnRead="@ReadTexts"
TItem="GridDataModel"
OnStateInit="@((GridStateEventArgs<GridDataModel> args) => OnGridStateInit(args))"
Groupable="true"
Class="my-grid">
<GridColumns>
<GridColumn Title="String 1" Field="@nameof(GridDataModel.S1)" />
<GridColumn Title="String 2" Field="@nameof(GridDataModel.S2)" />
<GridColumn Title="String 3" Field="@nameof(GridDataModel.S3)" />
<GridColumn Title="String 4" Field="@nameof(GridDataModel.S4)" />
<GridColumn Title="String 5" Field="@nameof(GridDataModel.S5)" />
</GridColumns>
</TelerikGrid>
@code {
private ObservableCollection<GridDataModel> GridData = new ObservableCollection<GridDataModel>();
protected override void OnInitialized()
{
base.OnInitialized();
GridData = new ObservableCollection<GridDataModel>
{
new(5, "Text D", "Text 5-2", "Text 5-3", "Text 5-4", "Text 5-5"),
new(1, "Text A", "Text 1-2", "Text 1-3", "Text 1-4", "Text 1-5"),
new(3, "Text C", "Text 3-2", "Text 3-3", "Text 3-4", "Text 3-5"),
new(4, "Text C", "Text 4-2", "Text 4-3", "Text 4-4", "Text 4-5"),
new(2, "Text B", "Text 2-2", "Text 2-3", "Text 2-4", "Text 2-5"),
};
}
protected async Task ReadTexts(GridReadEventArgs args)
{
var datasourceResult = GridData.ToDataSourceResult(args.Request);
// Determine if the data is grouped
if (args.Request.Groups.Any())
{
// Data is grouped, so we need to handle AggregateFunctionsGroup objects
var groups = datasourceResult.Data.Cast<AggregateFunctionsGroup>().ToList();
// Custom sort logic for grouped data based on your custom order: D, A, C, B
List<string> customOrder = new List<string> { "Text D", "Text A", "Text C", "Text B" };
groups = groups.OrderBy(group => customOrder.IndexOf(group.Key.ToString())).ToList();
args.Data = groups;
}
else
{
// Data is not grouped, so we can cast directly to GridDataModel
var orderedData = datasourceResult.Data.Cast<GridDataModel>()
.OrderBy(Text => GetCustomOrderIndex(Text.S1))
.ToList();
args.Data = orderedData;
}
args.Total = datasourceResult.Total;
args.AggregateResults = datasourceResult.AggregateResults;
}
private int GetCustomOrderIndex(string? value)
{
// Define the custom order
List<string> customOrder = new List<string> { "Text D", "Text A", "Text C", "Text B" };
// Return the index based on the custom order
return customOrder.IndexOf(value ?? string.Empty);
}
protected void OnGridStateInit(GridStateEventArgs<GridDataModel> args)
{
GridState<GridDataModel> desiredState = new GridState<GridDataModel>()
{
GroupDescriptors = new List<GroupDescriptor>()
{
new GroupDescriptor()
{
Member = nameof(GridDataModel.S1),
MemberType = typeof(string),
}
}
};
args.GridState = desiredState;
}
public class GridDataModel
{
public int Id { get; init; }
public string? S1 { get; set; }
public string? S2 { get; set; }
public string? S3 { get; set; }
public string? S4 { get; set; }
public string? S5 { get; set; }
public GridDataModel()
{
// Editable Telerik components require a parameterless constructor.
}
public GridDataModel(
int id,
string s1, string s2, string s3, string s4, string s5)
{
Id = id;
S1 = s1;
S2 = s2;
S3 = s3;
S4 = s4;
S5 = s5;
}
}
}