Adam O'Neil aosoftware.net 1/12/21
Unfortunately I don't have a fully open-source example, but I will show all my steps that I'm using to achieve server-side paging in queries used with Radzen Grid.
In a nutshell I have
Pager
component that lets you cycle through pages of query results. I don't use Linq Skip
and Take
methods. I use the Pager component's PageChanged
event to execute my query again with the new page number criteria.EditForm
component bound to my query
object. This is what sets my query page property, among other criteria properties.Pager
component. This renders as a pair of buttons pointing left and right (using the Open Iconic icons in the default Blazor project template.) The point of this is to have something user can click on to cycle pages backward and forward. Currently, I do not display the total number of pages in a query, just the current page. My page numbers are 0-based, but displayed as 1-based.<div class="d-flex align-items-center ml-2">
@if (Page > 0)
{
<button class="btn btn-outline-secondary" type="button" @onclick="@((args) => Navigate(-1))">
<span class="oi oi-caret-left"></span>
</button>
}
<span class="mx-3">@(Page + 1)</span>
<button class="btn btn-outline-secondary" type="button" @onclick="@((args) => Navigate(1))">
<span class="oi oi-caret-right"></span>
</button>
</div>
@code {
[Parameter]
public int Page { get; set; }
[Parameter]
public EventCallback<int> PageChanged { get; set; }
public void SetPage(int page)
{
Page = page;
StateHasChanged();
}
async Task Navigate(int direction)
{
Page += direction;
await PageChanged.InvokeAsync(Page);
}
}
Query<T>
class that encapsulates your query. Here's some info about how I do this from the Dapper.QX wiki. Your query class should have a Page
property with an [Offset]
attribute. On the page where you'll implement a pageable grid, have an instance of your query. My example is called ProjectsQuery
, and it has some criteria including an "active" filter and a start page of 0. I have a couple other necessary variables, one of the main grid
, and one representing the query result data
.RadzenGrid<ProjectsQueryResult> grid;
IEnumerable<ProjectsQueryResult> data;
ProjectsQuery query = new ProjectsQuery() { IsActive = true, Page = 0 };
EditForm
that binds to your query object. This will contain your Pager
component. Note that my example has a couple other things — a Radzen dropdown and text box, along with my ActiveFilter
component (a separate topic), my standard way of filtering for "active" or "inactive" items in a list.Note that the button
element has an @onclick
event that sets the query page to 0. This is so every time the user clicks Search, the results always start on the first page. Note also how the Pager
component handles the PageChanged
event by setting the query.Page
property to the Pager's currently selected page, and it calls the main page's RefreshList
method.
<EditForm Model="query" OnSubmit="RefreshList" class="form-inline">
<label class="mr-2">Manager:</label>
<RadzenDropDown Data="employees" ValueProperty="Id" TextProperty="DisplayName" @bind-Value="query.ManagerId" AllowClear="true" class="mr-2"/>
<label class="mr-2">Search:</label>
<RadzenTextBox @bind-Value="query.Search" class="mr-2"/>
<ActiveFilter @bind-Value="query.IsActive" Style="width:120px"/>
<button class="btn btn-secondary ml-2" @onclick="@((args) => query.Page = 0)">Search</button>
<Pager PageChanged="@(async (page) => { query.Page = page; await RefreshList(); })" @ref="pager" Page="@(query.Page ?? 0)"/>
</EditForm>
RefreshList
is a method in my main page. The important part of it looks like this. This is using my Dapper AspNetCore package to inject data access capabilities to components. This is a separate topic I can go into if you like. The important part of it here is to be able to execute my query
and fill the Radzen grid with data.@inject DapperCX<int, User> Data
async Task RefreshList()
{
// main grid
data = await Data.QueryAsync(query);
}