The Grid lets you read, save, load, and change its state through code. The state includes the Grid features that are controlled by the user, such as the current sorting, page number, applied grouping, column widths, and many others.
The Grid state is a generic class GridState<TItem>. The type depends on the type of the Grid model. The GridState<TItem> object exposes the following properties:
Information about each column's reorder index, width, visibility, locked state, Id parameter value and Field. The column order in the collection matches the column order in the Grid declaration. On the other hand, the Index property matches the current column's position in the UI. Id and Field are always null after deserialization, because these properties have no public setters.
The sum of all visible column widths. The initial value is always null regardless of the column configuration. The TableWidth value changes during column resizing together with ColumnStates and theOnStateChanged event does not fire separately for it. When you resize a column programmatically, and all other columns already have widths, you must update the TableWidth too, otherwise the other columns will resize unexpectedly.
The OnStateInit event fires when the Grid is initializing. Use this event to:
Define initial state, for example default initial sorting;
Load and apply state that was previously saved in a database or in localStorage.
The generic event argument is of type GridStateEventArgs<TItem> and has a GridState property. See Information in the Grid State for details.
If you change the column order or number of columns in the Grid declaration, this can break state restore. In such cases, either ignore the stored column state, or implement custom logic to restore only the columns that still exist in the Grid.
To set the initial visibility of columns, better use the Visible parameter, rather than conditional markup for the whole column. The Visible parameter values will be present in the Grid state and the columns collection count will remain the same. This makes it easier to reconcile changes.
The example below shows how to apply initial sorting, filtering and grouping.
OnStateChanged fires when the user performs an action that changes the value of a property in the Grid state. The event argument is of type GridStateEventArgs<TItem> and exposes these properties:
Property
Type
Description
PropertyName
string
Information about what changed in the Grid state. The possible values match the property names of the GridState object. The possible values for the PropertyName are SortDescriptors, FilterDescriptors, SearchFilter, GroupDescriptors, Page, Skip, CollapsedGroups, ColumnStates, ExpandedItems, InsertedItem, OriginalEditItem, EditItem.
GridState
GridState<TItem>
The current (up-to-date) Grid state object.
Here is some additional information about certain PropertyName values:
EditItem is used when the user starts editing an existing item.
OriginalEditItem is used when the user exits edit or insert mode via save or cancel.
ColumnStates is used for several column actions such as hiding, showing, locking, reordering and resizing.
Some user actions will trigger two OnStateChanged events with a different PropertyName each time. These include filtering, searching and grouping. For example, filtering resets the current page to 1. First, the event will fire with PropertyName equal to "FilterDescriptors", and then PropertyName will be "Page". However, the GridState property of the event argument will provide correct information about the overall Grid state in both event handler executions.
We recommend using an async Task handler for the OnStateChanged event, in order to reduce re-rendering and avoid blocking UI updates if the handler will wait for a service to save the Grid state somewhere.
To observe the changes in the Grid state more easily, copy and run the following example in a local app and at full screen.
SetStateAsync receives an instance of a GridState<TItem> object and applies it to the Grid. For example, you can have a button that puts the Grid in a certain configuration programmatically, for example sort or filter the data, enter or exit edit mode, expand or collapse groups or detail Grids, etc.
If you want to make changes to the current Grid state:
First, get the current state with the GetState method.
Apply the desired modifications to the obtained GridState object.
Set the modified state object via the SetStateAsync method.
Do not use GetState() in the OnStateInit or OnStateChanged events. Do not use SetStateAsync() in OnStateInit. Instead, get or set the GridState property of the event argument.
Avoid calling SetStateAsync in the Grid CRUD methods (such as OnRead, OnUpdate, OnEdit, OnCreate, OnCancel). Doing so may lead to unexpected results because the Grid has more logic to execute after these events. Setting the Grid state fires OnRead, so calling SetStateAsync() in this handler can lead to an endless loop.
To reset the Grid state to its initial markup configuration, call SetStateAsync(null).
To reset the Grid state to a completely new configuration, create a new GridState<T>() and apply the settings there. Then pass the state object to SetStateAsync().
The tabs below show how to set the Grid state and control filtering, sorting and other Grid features.
If you want to set an initial state to the Grid, use a similar snippet, but in the OnStateInit event
RAZOR
@usingTelerik.DataSource<TelerikGrid@ref="@GridRef"Data="@GridData"Pageable="true"Sortable="true"SortMode="@SortMode.Multiple"Height="400px"><GridToolBarTemplate><TelerikButtonThemeColor="@ThemeConstants.Button.ThemeColor.Primary"OnClick="@SetGridSort">Sort Grid by HireDate</TelerikButton><label><TelerikCheckBox@bind-Value="@ShouldResetSortState"/>
Clear Existing Sorting On Button Click
</label></GridToolBarTemplate><GridColumns><GridColumnField="@(nameof(Employee.Name))"Title="Employee Name"/><GridColumnField="@(nameof(Employee.Team))"Title="Team"/><GridColumnField="@(nameof(Employee.HireDate))"Title="Hire Date"DisplayFormat="{0:d}"/><GridColumnField="@(nameof(Employee.IsOnLeave))"Title="Is On Leave"/></GridColumns></TelerikGrid>@code {
private TelerikGrid<Employee>? GridRef { get; set; }
private List<Employee> GridData { get; set; } = new();
private bool ShouldResetSortState { get; set; } = true;
private async Task SetGridSort()
{
if (GridRef != null)
{
var gridState = GridRef.GetState();
if (ShouldResetSortState)
{
// Remove any existing sorts.
gridState.SortDescriptors.Clear();
}
SortDescriptor? hireDateSortDescriptor = gridState.SortDescriptors
.Where(x => x.Member == nameof(Employee.HireDate)).FirstOrDefault();
if (hireDateSortDescriptor != null)
{
// Update the existing HireDate sort if it exists.
hireDateSortDescriptor.SortDirection = ListSortDirection.Descending;
}
else
{
// Add a new sort descriptor.
// In multi-column sorting scenarios
// you can also insert the new SortDescriptor
// before the existing ones to control the sort priority.
gridState.SortDescriptors.Add(new SortDescriptor()
{
Member = nameof(Employee.HireDate),
SortDirection = ListSortDirection.Descending
});
}
await GridRef.SetStateAsync(gridState);
}
}
protected override void OnInitialized()
{
for (int i = 1; i <= 30; i++)
{
GridData.Add(new Employee()
{
Id = i,
Name = $"Name {i}",
Team = $"Team {i % 5 + 1}",
HireDate = DateTime.Today.AddDays(-Random.Shared.Next(1, 3000)),
IsOnLeave = i % 4 == 0 ? true : false
});
}
}
public class Employee
{
public int Id { get; set; }
public string Name { get; set; } = string.Empty;
public string Team { get; set; } = string.Empty;
public DateTime HireDate { get; set; }
public bool IsOnLeave { get; set; }
}
}
RAZOR
@usingTelerik.DataSource<TelerikGrid@ref="@GridRef"Data="@GridData"Pageable="true"FilterMode="@GridFilterMode.FilterRow"Height="400px"><GridToolBarTemplate><TelerikButtonThemeColor="@ThemeConstants.Button.ThemeColor.Success"OnClick="@(()=>SetGridFilters(false))">Filter Grid by Team</TelerikButton><TelerikButtonThemeColor="@ThemeConstants.Button.ThemeColor.Primary"OnClick="@(()=>SetGridFilters(true))">Filter Grid by Team and HireDate</TelerikButton><spanclass="k-separator"></span><TelerikButtonOnClick="@RemoveGridFilters">Remove All Filters</TelerikButton></GridToolBarTemplate><GridColumns><GridColumnField="@(nameof(Employee.Name))"Title="Employee Name"/><GridColumnField="@(nameof(Employee.Team))"Title="Team"/><GridColumnField="@(nameof(Employee.HireDate))"Title="Hire Date"DisplayFormat="{0:d}"/><GridColumnField="@(nameof(Employee.IsOnLeave))"Title="Is On Leave"/></GridColumns></TelerikGrid>@code {
private TelerikGrid<Employee>? GridRef { get; set; }
private List<Employee> GridData { get; set; } = new();
private async Task SetGridFilters(bool shouldFilterSecondColumn)
{
if (GridRef != null)
{
var gridState = GridRef.GetState();
// Find the Team CompositeFilterDescriptor if it exists.
CompositeFilterDescriptor? teamCFD = gridState.FilterDescriptors.Cast<CompositeFilterDescriptor>()
.Where(x => x.FilterDescriptors.Cast<FilterDescriptor>().First().Member == nameof(Employee.Team))
.FirstOrDefault();
if (teamCFD != null)
{
// Update the existing Team CompositeFilterDescriptor.
var teamFilterDescriptors = teamCFD.FilterDescriptors.Cast<FilterDescriptor>();
// When using a filter row, the column's CompositeFilterDescriptor
// always contains one FilterDescriptor.
FilterDescriptor firstTeamFD = teamFilterDescriptors.First();
firstTeamFD.Operator = FilterOperator.IsEqualTo;
firstTeamFD.Value = "Team 1";
}
else
{
// Create a new Team CompositeFilterDescriptor.
var teamFdCollection = new FilterDescriptorCollection();
teamFdCollection.Add(new FilterDescriptor()
{
Member = nameof(Employee.Team),
MemberType = typeof(string),
Operator = FilterOperator.IsEqualTo,
Value = "Team 1"
});
// Add one CompositeFilterDescriptor per column.
gridState.FilterDescriptors.Add(new CompositeFilterDescriptor()
{
// The LogicalOperator property doesn't matter, because
// there is only one FilterDescritor in the CompositeFilterDescriptor.
FilterDescriptors = teamFdCollection
});
}
// Find the HireDate CompositeFilterDescriptor if it exists.
CompositeFilterDescriptor? hireDateCFD = gridState.FilterDescriptors.Cast<CompositeFilterDescriptor>()
.Where(x => x.FilterDescriptors.Cast<FilterDescriptor>().First().Member == nameof(Employee.HireDate))
.FirstOrDefault();
if (hireDateCFD != null)
{
// Instead of changing the existing CompositeFilterDescriptor,
// you can also remove it and create a new one.
gridState.FilterDescriptors.Remove(hireDateCFD);
}
if (shouldFilterSecondColumn)
{
var hireDateFdCollection = new FilterDescriptorCollection();
hireDateFdCollection.Add(new FilterDescriptor()
{
Member = nameof(Employee.HireDate),
MemberType = typeof(DateTime),
Operator = FilterOperator.IsGreaterThanOrEqualTo,
Value = DateTime.Today.AddYears(-3)
});
gridState.FilterDescriptors.Add(new CompositeFilterDescriptor()
{
FilterDescriptors = hireDateFdCollection
});
}
await GridRef.SetStateAsync(gridState);
}
}
private async Task RemoveGridFilters()
{
if (GridRef != null)
{
var gridState = GridRef.GetState();
gridState.FilterDescriptors.Clear();
await GridRef.SetStateAsync(gridState);
}
}
protected override void OnInitialized()
{
for (int i = 1; i <= 30; i++)
{
GridData.Add(new Employee()
{
Id = i,
Name = $"Name {i}",
Team = $"Team {i % 5 + 1}",
HireDate = DateTime.Today.AddDays(-Random.Shared.Next(1, 3000)),
IsOnLeave = i % 4 == 0 ? true : false
});
}
}
public class Employee
{
public int Id { get; set; }
public string Name { get; set; } = string.Empty;
public string Team { get; set; } = string.Empty;
public DateTime HireDate { get; set; }
public bool IsOnLeave { get; set; }
}
}
RAZOR
@usingTelerik.DataSource<TelerikGrid@ref="@GridRef"Data="@GridData"Pageable="true"FilterMode="@GridFilterMode.FilterMenu"Height="400px"><GridToolBarTemplate><TelerikButtonThemeColor="@ThemeConstants.Button.ThemeColor.Success"OnClick="@(()=>SetTeamFilter(false))">Filter Grid by Team 1</TelerikButton><TelerikButtonThemeColor="@ThemeConstants.Button.ThemeColor.Primary"OnClick="@(()=>SetTeamFilter(true))">Filter Grid by Team 1 or 3</TelerikButton><spanclass="k-separator"></span><TelerikButtonOnClick="@RemoveGridFilters">Remove All Filters</TelerikButton></GridToolBarTemplate><GridColumns><GridColumnField="@(nameof(Employee.Name))"Title="Employee Name"/><GridColumnField="@(nameof(Employee.Team))"Title="Team"/><GridColumnField="@(nameof(Employee.HireDate))"Title="Hire Date"DisplayFormat="{0:d}"/><GridColumnField="@(nameof(Employee.IsOnLeave))"Title="Is On Leave"/></GridColumns></TelerikGrid>@code {
private TelerikGrid<Employee>? GridRef { get; set; }
private List<Employee> GridData { get; set; } = new();
private async Task SetTeamFilter(bool shouldSetSecondFilter)
{
if (GridRef != null)
{
var gridState = GridRef.GetState();
// Find the Team CompositeFilterDescriptor if it exists.
CompositeFilterDescriptor? teamCFD = gridState.FilterDescriptors.Cast<CompositeFilterDescriptor>()
.Where(x => x.FilterDescriptors.Cast<FilterDescriptor>().First().Member == nameof(Employee.Team))
.FirstOrDefault();
if (teamCFD != null)
{
// Update the existing Team CompositeFilterDescriptor.
teamCFD.LogicalOperator = FilterCompositionLogicalOperator.Or;
var teamFilterDescriptors = teamCFD.FilterDescriptors.Cast<FilterDescriptor>();
// When using a filter menu, the column's CompositeFilterDescriptor
// always contains two FilterDescriptors.
FilterDescriptor firstTeamFD = teamFilterDescriptors.First();
firstTeamFD.Operator = FilterOperator.IsEqualTo;
firstTeamFD.Value = "Team 1";
// Set a null FilterDescriptor Value and IsEqualTo Operator
// to disable a filter.
FilterDescriptor secondTeamFD = teamFilterDescriptors.Last();
secondTeamFD.Operator = FilterOperator.IsEqualTo;
secondTeamFD.Value = shouldSetSecondFilter ? "Team 3" : null;
}
else
{
// Create a new Team CompositeFilterDescriptor.
var fdCollection = new FilterDescriptorCollection();
fdCollection.Add(new FilterDescriptor()
{
Member = nameof(Employee.Team),
MemberType = typeof(string),
Operator = FilterOperator.IsEqualTo,
Value = "Team 1"
});
fdCollection.Add(new FilterDescriptor()
{
Member = nameof(Employee.Team),
MemberType = typeof(string),
Operator = FilterOperator.IsEqualTo,
Value = shouldSetSecondFilter ? "Team 3" : null
});
// Add one CompositeFilterDescriptor per column.
gridState.FilterDescriptors.Add(new CompositeFilterDescriptor()
{
LogicalOperator = FilterCompositionLogicalOperator.Or,
FilterDescriptors = fdCollection
});
}
await GridRef.SetStateAsync(gridState);
}
}
private async Task RemoveGridFilters()
{
if (GridRef != null)
{
var gridState = GridRef.GetState();
gridState.FilterDescriptors.Clear();
await GridRef.SetStateAsync(gridState);
}
}
protected override void OnInitialized()
{
for (int i = 1; i <= 30; i++)
{
GridData.Add(new Employee()
{
Id = i,
Name = $"Name {i}",
Team = $"Team {i % 5 + 1}",
HireDate = DateTime.Today.AddDays(-Random.Shared.Next(1, 3000)),
IsOnLeave = i % 4 == 0 ? true : false
});
}
}
public class Employee
{
public int Id { get; set; }
public string Name { get; set; } = string.Empty;
public string Team { get; set; } = string.Empty;
public DateTime HireDate { get; set; }
public bool IsOnLeave { get; set; }
}
}
RAZOR
@usingTelerik.DataSource<TelerikGrid@ref="@GridRef"Data="@GridData"Pageable="true"Sortable="true"><GridToolBar><GridToolBarCustomTool><TelerikButtonIcon="@SvgIcon.Search"ThemeColor="@ThemeConstants.Button.ThemeColor.Primary"OnClick="@OnSearchButtonClick">Search Programmatically</TelerikButton><TelerikButtonIcon="@SvgIcon.X"OnClick="@OnClearButtonClick">Clear Search</TelerikButton></GridToolBarCustomTool><GridToolBarSearchBoxTool/></GridToolBar><GridColumns><GridColumnField="@nameof(GridModel.Name)"/><GridColumnField="@nameof(GridModel.Description)"/></GridColumns></TelerikGrid>@code{privateTelerikGrid<GridModel>? GridRef {get;set;}privateList<GridModel> GridData {get;set;}=new();privateasyncTaskOnSearchButtonClick(){if(GridRef isnull){return;}GridState<GridModel> gridState = GridRef.GetState();string searchString =$"{(char)Random.Shared.Next(97,123)}{(char)Random.Shared.Next(97,123)}";CompositeFilterDescriptor cfd =new();
cfd.LogicalOperator = FilterCompositionLogicalOperator.Or;
cfd.FilterDescriptors =newFilterDescriptorCollection();// Add one FilterDesccriptor for each string column
cfd.FilterDescriptors.Add(newFilterDescriptor(){
Member =nameof(GridModel.Name),
MemberType =typeof(string),
Operator = FilterOperator.Contains,
Value = searchString
});
cfd.FilterDescriptors.Add(newFilterDescriptor(){
Member =nameof(GridModel.Description),
MemberType =typeof(string),
Operator = FilterOperator.Contains,
Value = searchString
});
gridState.SearchFilter = cfd;await GridRef.SetStateAsync(gridState);}privateasyncTaskOnClearButtonClick(){if(GridRef isnull){return;}GridState<GridModel> gridState = GridRef.GetState();(gridState.SearchFilter asCompositeFilterDescriptor)?.FilterDescriptors.Clear();await GridRef.SetStateAsync(gridState);}protectedoverridevoidOnInitialized(){for(int i =1; i <=500; i++){
GridData.Add(newGridModel(){
Id = i,
Name =$"{(char)Random.Shared.Next(65,91)}{(char)Random.Shared.Next(65,91)} "+$"{(char)Random.Shared.Next(65,91)}{(char)Random.Shared.Next(65,91)}{i}",
Description =$"{(char)Random.Shared.Next(97,123)}{(char)Random.Shared.Next(97,123)} "+$"{(char)Random.Shared.Next(97,123)}{(char)Random.Shared.Next(97,123)}{i}"});}}publicclassGridModel{publicint Id {get;set;}publicstring Name {get;set;}=string.Empty;publicstring Description {get;set;}=string.Empty;}}
RAZOR
@usingTelerik.DataSource<TelerikGrid@ref="@GridRef"Data="@GridData"Pageable="true"Groupable="true"><GridToolBarTemplate><TelerikButtonThemeColor="@ThemeConstants.Button.ThemeColor.Success"OnClick="@(()=>SetGridGroups(false))">Group Grid by Team</TelerikButton><TelerikButtonThemeColor="@ThemeConstants.Button.ThemeColor.Primary"OnClick="@(()=>SetGridGroups(true))">Group Grid by Team and IsOnLeave</TelerikButton><spanclass="k-separator"></span><TelerikButtonOnClick="@RemoveGridGroups">Remove All Groups</TelerikButton></GridToolBarTemplate><GridColumns><GridColumnField="@(nameof(Employee.Name))"Title="Employee Name"/><GridColumnField="@(nameof(Employee.Team))"/><GridColumnField="@(nameof(Employee.HireDate))"Title="Hire Date"DisplayFormat="{0:d}"/><GridColumnField="@(nameof(Employee.IsOnLeave))"Title="Is On Leave"/></GridColumns></TelerikGrid>@code {
private TelerikGrid<Employee>? GridRef { get; set; }
private List<Employee> GridData { get; set; } = new();
private async Task SetGridGroups(bool shouldGroupBySecondColumn)
{
if (GridRef != null)
{
var gridState = GridRef.GetState();
// Remove any existing Grid groups
// You can also modify or reorder existing GroupDescriptors.
gridState.GroupDescriptors.Clear();
gridState.GroupDescriptors.Add(new GroupDescriptor()
{
Member = nameof(Employee.Team),
MemberType = typeof(string),
// https://feedback.telerik.com/blazor/1544196-allow-sorting-the-grouped-column
SortDirection = ListSortDirection.Ascending
});
if (shouldGroupBySecondColumn)
{
gridState.GroupDescriptors.Add(new GroupDescriptor()
{
Member = nameof(Employee.IsOnLeave),
MemberType = typeof(bool),
// https://feedback.telerik.com/blazor/1544196-allow-sorting-the-grouped-column
SortDirection = ListSortDirection.Descending
});
}
await GridRef.SetStateAsync(gridState);
}
}
private async Task RemoveGridGroups()
{
if (GridRef != null)
{
var gridState = GridRef.GetState();
gridState.GroupDescriptors.Clear();
await GridRef.SetStateAsync(gridState);
}
}
protected override void OnInitialized()
{
for (int i = 1; i <= 30; i++)
{
GridData.Add(new Employee()
{
Id = i,
Name = $"Name {i}",
Team = $"Team {i % 5 + 1}",
HireDate = DateTime.Today.AddDays(-Random.Shared.Next(1, 3000)),
IsOnLeave = i % 4 == 0 ? true : false
});
}
}
public class Employee
{
public int Id { get; set; }
public string Name { get; set; } = string.Empty;
public string Team { get; set; } = string.Empty;
public DateTime HireDate { get; set; }
public bool IsOnLeave { get; set; }
}
}
RAZOR
<TelerikGrid@ref="@GridRef"Data="@CategoryData"Pageable="true"PageSize="2"><GridToolBarTemplate><TelerikDropDownListData="@CategoryData"@bind-Value="@DropDownListCategoryId"TextField="@nameof(Category.Name)"ValueField="@nameof(Category.Id)"></TelerikDropDownList><TelerikButtonThemeColor="@ThemeConstants.Button.ThemeColor.Success"OnClick="@ExpandCategory">Expand Category</TelerikButton><spanclass="k-separator"></span><TelerikButtonThemeColor="@ThemeConstants.Button.ThemeColor.Primary"OnClick="@ExpandAll">Expand All Categories</TelerikButton><spanclass="k-separator"></span><TelerikButtonOnClick="@CollapseAll">Collapse All Categories</TelerikButton></GridToolBarTemplate><GridColumns><GridColumnField="@(nameof(Category.Id))"Width="80px"/><GridColumnField="@(nameof(Category.Name))"Title="Category Name"/></GridColumns><DetailTemplateContext="category"><TelerikGridData="@ProductData.Where(x => x.CategoryId == category.Id)"><GridColumns><GridColumnField="@(nameof(Product.Name))"Title="Product Name"/><GridColumnField="@(nameof(Product.Price))"DisplayFormat="{0:c2}"/><GridColumnField="@(nameof(Product.Quantity))"/></GridColumns></TelerikGrid></DetailTemplate></TelerikGrid>@code{privateTelerikGrid<Category>? GridRef {get;set;}privateList<Category> CategoryData {get;set;}=new();privateList<Product> ProductData {get;set;}=new();privateint DropDownListCategoryId {get;set;}=1;privateasyncTaskExpandCategory(){if(GridRef !=null){var gridState = GridRef.GetState();var categoryToExpand = CategoryData.First(x => x.Id == DropDownListCategoryId);
gridState.ExpandedItems.Add(categoryToExpand);await GridRef.SetStateAsync(gridState);}}privateasyncTaskExpandAll(){if(GridRef !=null){var gridState = GridRef.GetState();
gridState.ExpandedItems = CategoryData;await GridRef.SetStateAsync(gridState);}}privateasyncTaskCollapseAll(){if(GridRef !=null){var gridState = GridRef.GetState();
gridState.ExpandedItems.Clear();await GridRef.SetStateAsync(gridState);}}protectedoverridevoidOnInitialized(){var categoryCount =3;for(int i =1; i <= categoryCount; i++){
CategoryData.Add(newCategory(){
Id = i,
Name =$"Category {i}"});}for(int i =1; i <=12; i++){
ProductData.Add(newProduct(){
Id = i,
CategoryId = i % categoryCount +1,
Name =$"Product {i}",
Price = Random.Shared.Next(1,100)*1.23m,
Quantity = Random.Shared.Next(0,100)});}}publicclassCategory{publicint Id {get;set;}publicstring Name {get;set;}=string.Empty;}publicclassProduct{publicint Id {get;set;}publicint CategoryId {get;set;}publicstring Name {get;set;}=string.Empty;publicdecimal Price {get;set;}publicint Quantity {get;set;}}}
RAZOR
<TelerikGrid@ref="@GridRef"Data="@GridData"Pageable="true"Reorderable="true"Resizable="true"><GridToolBarTemplate><TelerikButtonThemeColor="@ThemeConstants.Button.ThemeColor.Success"OnClick="@ReorderPriceAndQuantity">Reorder Price and Quantity</TelerikButton><TelerikButtonThemeColor="@ThemeConstants.Button.ThemeColor.Success"OnClick="@MakeIdColumnLast">Make Id Column Last</TelerikButton><TelerikButtonThemeColor="@ThemeConstants.Button.ThemeColor.Success"OnClick="@ResizeColumns">Resize Columns</TelerikButton><spanclass="k-separator"></span><TelerikButtonOnClick="@ResetColumns">Reset Column Configuration</TelerikButton></GridToolBarTemplate><GridColumns><GridColumnField="@(nameof(Product.Id))"Width="80px"/><GridColumnField="@(nameof(Product.Name))"Title="Product Name"/><GridColumnField="@(nameof(Product.Price))"DisplayFormat="{0:c2}"/><GridColumnField="@(nameof(Product.Quantity))"/><GridColumnField="@(nameof(Product.ReleaseDate))"DisplayFormat="{0:d}"/></GridColumns></TelerikGrid>@code {
private TelerikGrid<Product>? GridRef { get; set; }
private List<Product> GridData { get; set; } = new();
private async Task ReorderPriceAndQuantity()
{
if (GridRef != null)
{
var gridState = GridRef.GetState();
// Get column by its index in the Grid markup.
var priceColumnState = gridState.ColumnStates.ElementAt(2);
var priceColumnIndex = priceColumnState.Index;
// Get column by a parameter such as Field or Id.
var quantityColumnState = gridState.ColumnStates.First(x => x.Field == nameof(Product.Quantity));
var quantityColumnIndex = quantityColumnState.Index;
priceColumnState.Index = quantityColumnIndex;
quantityColumnState.Index = priceColumnIndex;
await GridRef.SetStateAsync(gridState);
}
}
private async Task MakeIdColumnLast()
{
if (GridRef != null)
{
var gridState = GridRef.GetState();
var idColumnState = gridState.ColumnStates.First(x => x.Field == nameof(Product.Id));
var oldIdIndex = idColumnState.Index;
idColumnState.Index = gridState.ColumnStates.Count - 1;
foreach (var columnState in gridState.ColumnStates)
{
// Decrement the indexes of all columns that were after Id.
if (columnState.Field != nameof(Product.Id) && columnState.Index > oldIdIndex)
{
--columnState.Index;
}
}
await GridRef.SetStateAsync(gridState);
}
}
private async Task ResizeColumns()
{
if (GridRef != null)
{
var gridState = GridRef.GetState();
int newColumnWidth = 160;
foreach (GridColumnState columnState in gridState.ColumnStates)
{
columnState.Width = $"{newColumnWidth}px";
}
gridState.TableWidth = $"{newColumnWidth * gridState.ColumnStates.Count}px";
await GridRef.SetStateAsync(gridState);
}
}
private async Task ResetColumns()
{
if (GridRef != null)
{
var gridState = GridRef.GetState();
gridState.ColumnStates = new List<GridColumnState>();
gridState.TableWidth = null;
await GridRef.SetStateAsync(gridState);
}
}
protected override void OnInitialized()
{
for (int i = 1; i <= 5; i++)
{
GridData.Add(new Product()
{
Id = i,
Name = $"Product {i}",
Price = Random.Shared.Next(1, 100) * 1.23m,
Quantity = Random.Shared.Next(0, 100),
ReleaseDate = DateTime.Today.AddDays(-Random.Shared.Next(150, 3000))
});
}
}
public class Product
{
public int Id { get; set; }
public string Name { get; set; } = string.Empty;
public decimal Price { get; set; }
public int Quantity { get; set; }
public DateTime ReleaseDate { get; set; }
}
}
If you want to alter the filters for a specific column, do not use more than one FilterDescriptor in FilterRow mode, and more than two FilterDescriptors in FilterMenu mode. Otherwise additional descriptors will not show up in the UI. This means that you may need to replace or modify an existing descriptor, rather than add a new one.
Inactive filter descriptors in FilterMenu mode are distinguished by their nullValue.
State properties that pertain to data items (for example, edited item or selected items) are typed according to the Grid model. If you restore such data, make sure to implement appropriate comparison checks - by default the .Equals() check for a class (object) is a reference check and the reference from the restored state is very unlikely to match the current reference in the Grid data. Thus, you may want to override the .Equals() method of the Grid model class, so that it compares by ID, or otherwise re-populate the models in the state object with the new model references from the Grid data.