--- title: Pin Rows at the Top of the Grid description: Learn how to pin (freeze, lock) one or more rows at the top of the Grid, so that they don't scroll together with the other table rows. type: how-to page_title: How to Pin Rows on top of the Grid slug: grid-kb-pin-rows position: tags: blazor, grid, pin, sticky, freeze, lock ticketid: 1676279 res_type: kb --- ## Environment
Product Grid for Blazor
## Description This KB article answers the following questions: * How to pin one or more rows on top of the Grid so that they are always visible to the users. * How to lock Grid rows, so that they don't scroll with the other table rows? * How to implement frozen rows at the top of the Grid? * How to make some Grid rows stick to the top of the component's data area during scrolling? ## Solution To freeze Grid rows you can: * Use the [`OnRead event`](slug:components/grid/manual-operations) to place the row/rows on top of the data collection for the Grid. * Use the [`OnRowRender event`](slug:grid-events#onrowrender) to add a custom CSS class to the rows you want to pin. * Dynamically calculate the `top` CSS rule with JavaScript. * Register the JavaScript file.
````C# @* Pin rows to the Grid *@ @using Telerik.DataSource @using Telerik.DataSource.Extensions @inject IJSRuntime js @code { private void RowRenderHandler(GridRowRenderEventArgs args) { var gridRow = args.Item as Employee; foreach (var pinnedRowIndex in pinnedGridRows) { if (gridRow.ID == pinnedRowIndex) { args.Class = "k-grid-row-sticky"; } } } public List pinnedGridRows { get; set; } = new List() { 5, 12, 21 }; protected override async Task OnAfterRenderAsync(bool firstRender) { await js.InvokeVoidAsync("pinElements", ".k-grid-row-sticky", 40); } public int pinnedRowIndex { get; set; } = 20; public List SourceData { get; set; } private List PinnedTopRow(DataSourceResult result) { List _data = result.Data.Cast().ToList(); var indexToInsert = 0; foreach (var pinnedRow in pinnedGridRows) { var rowToBePinned = _data.FirstOrDefault(x => x.ID == pinnedRow); _data.Remove(rowToBePinned); _data.Insert(indexToInsert, rowToBePinned); indexToInsert++; } return _data; } protected async Task ReadItems(GridReadEventArgs args) { await Task.Delay(1000); var datasourceResult = SourceData.ToDataSourceResult(args.Request); args.Data = PinnedTopRow(datasourceResult); args.Total = datasourceResult.Total; } protected override void OnInitialized() { SourceData = GenerateData(); } private List GenerateData() { var result = new List(); var rand = new Random(); for (int i = 0; i < 100; i++) { result.Add(new Employee() { ID = i, Name = "Name " + i, HireDate = DateTime.Now.Date.AddDays(rand.Next(-20, 20)) }); } return result; } public class Employee { public int ID { get; set; } public string Name { get; set; } public DateTime HireDate { get; set; } } } ```` ````JavaScript @* Calculate the top CSS rule *@ function pinElements(pinCSSClass, rowHeight) { let elements = document.querySelectorAll(pinCSSClass); elements.forEach((element, index) => { element.style.top = index * rowHeight + "px" }); } ````