Hi there,
currently the grid component does not provide a feature to set a specific position in virtual scrolling mode.
My team has currently implemented a workaround via javascript interop call to set a specific position. The workaround basically calculates the "scroll value" (we reverse engineered this value by looking at the Telerik js code) and passes it to the jQuery scrollTop() function. This results in an update of the scrollbar which in return triggers the OnReadItems event where we fetch the items based on the given skip and take values.
This workaround does not seem to work in all cases and is somewhat unreliable hence i'm requesting an official feature to set a specific position without the javascript hack.
What do you say?
So lonG
Daniel
Hi Marin,
thanks again, much appreciated, perfect answer.
So lonG
Daniel
Hi Daniel,
The key difference is that an "async Task" method waits for every await-ed call in there to finish before continuing to the next line. This ensures data and references and objects are in sync. An "async void" method does not do that and so it can cause issues with the UI becoming out of sync with the data - the method will exit, the UI will repaint, but the await-ed operations are likely to not have completed yet.
So, if you only want to send some data and you don't need a response from that (like saving the grid state in realtime) - an async void is OK. In general, it can cause a variety of issues, and I recommend always using an async Task for an event handler related to UI (as for your own backend - that's up to your logic and needs). For example, event handlers for the CRUD operations of the grid must always be "async Task" for this same reason.
On learning resources - I am not in a position to endorse brands or materials, but there are many tutorials and information about the async-await pattern and how it works with UI that you may want to look into for more details.
Regards,
Marin Bratanov
Progress Telerik
Hello Marin,
thanks for the fast reply. The state feature is freakin' awesome. I didn't take notice of it when reading the release notes for version 2.9.0.
Let me ask a final question about the section in the docs:
"We recommend that you use an async void handler for the OnStateChanged event in order to reduce re-rendering and to avoid blocking the UI update while waiting for the service to store the data. Doing so will let the UI thread continue without waiting for the storage service to complete."
Is using `async void` a general approach to reduce re-rendering in connection with your components? Can you provide a source where i can learn more about re-rendering and UI thread handling?
So lonG
Daniel
Hello Daniel,
You can do this with the grid state: https://docs.telerik.com/blazor-ui/components/grid/state
Here's an example I made for you:
<TelerikButton OnClick="@ScrollToPageSix">Scroll to page 6</TelerikButton>
<TelerikGrid Data=@GridData
ScrollMode="@GridScrollMode.Virtual"
Height="480px" RowHeight="60" PageSize="@PageSize"
Sortable="true" FilterMode="@GridFilterMode.FilterMenu"
OnStateInit="@((GridStateEventArgs<SampleData> args) => OnStateInitHandler(args))" @ref="@GridRef">
<GridColumns>
<GridColumn Field="Id" />
<GridColumn Field="Name" Title="First Name" />
<GridColumn Field="LastName" Title="Last Name" />
<GridColumn Field="HireData" Width="200px">
<Template>
@((context as SampleData).HireDate.ToString("MMMM dd, yyyy"))
</Template>
</GridColumn>
</GridColumns>
</TelerikGrid>
@code {
// managing the state to set scrolling
TelerikGrid<SampleData> GridRef { get; set; }
int PageSize { get; set; } = 20;
async Task OnStateInitHandler(GridStateEventArgs<SampleData> args)
{
var state = new GridState<SampleData>()
{
Skip = 3 * PageSize // 3 pages times the page size
};
args.GridState = state;
}
async Task ScrollToPageSix()
{
var state = new GridState<SampleData>()
{
Skip = 6 * PageSize // 6 pages times the page size
};
GridRef.SetState(state);
}
//data generation from the docs
public List<SampleData> GridData { get; set; }
protected override async Task OnInitializedAsync()
{
GridData = await GetData();
}
private async Task<List<SampleData>> GetData()
{
return Enumerable.Range(1, 1000).Select(x => new SampleData
{
Id = x,
Name = $"name {x}",
LastName = $"Surname {x}",
HireDate = DateTime.Now.Date.AddDays(-x)
}).ToList();
}
public class SampleData
{
public int Id { get; set; }
public string Name { get; set; }
public string LastName { get; set; }
public DateTime HireDate { get; set; }
}
}
Regards,
Marin Bratanov
Progress Telerik