Back to Devexpress

Paging in Blazor TreeList

blazor-405040-components-treelist-paging-and-scrolling-paging.md

latest20.7 KB
Original Source

Paging in Blazor TreeList

  • Jan 20, 2026
  • 10 minutes to read

The DevExpress Blazor TreeList splits data rows across multiple pages and displays a pager to enable data navigation. The pager can contain a page size selector that allows users to change the page size at runtime. You can also use the control’s API to build a custom pager control or to navigate between pages automatically based on your application’s logic.

Run Demo

Page Size

Use the PageSize property to specify the maximum number of rows displayed on a page. You can display the page size selector that allows users to change the page size at runtime. Once a user selects a new value in this selector, the PageSize property value is updated and the PageSizeChanged event fires.

If a value does not fit into a cell as a single line, the cell displays multiple lines of text. The TreeList component automatically adjusts its height based on the total number of lines displayed on the page. Set the TextWrapEnabled property to false to display every row in one line and keep the same page height regardless of row data. Note that the last page can display fewer rows than the PageSize.

The following code sample displays 4 single-line nodes on each TreeList page:

razor
@inject EmployeeTaskService EmployeeTaskService

<DxTreeList Data="TreeListData"
            KeyFieldName="Id"
            ParentKeyFieldName="ParentId"
            PageSize="4"
            TextWrapEnabled="false">
    <Columns>
        <DxTreeListDataColumn FieldName="Name" Caption="Task" />
        <DxTreeListDataColumn FieldName="EmployeeName" />
        <DxTreeListDataColumn FieldName="StartDate" />
        <DxTreeListDataColumn FieldName="DueDate" />
    </Columns>
</DxTreeList>

@code {
    List<EmployeeTask> TreeListData { get; set; }

    protected override void OnInitialized() {
        TreeListData = EmployeeTaskService.GenerateData();
    }
}
csharp
public class EmployeeTask {
    public int Id { get; set; }
    public int ParentId { get; set; }
    public string Name { get; set; }
    public string EmployeeName { get; set; }
    public DateTime StartDate { get; set; }
    public DateTime DueDate { get; set; }
    public int Progress { get; set; }
    public EmployeeTask() { }
    public EmployeeTask(
        int id,
        int parentId,
        string name,
        string employeeName,
        DateTime startDate,
        DateTime dueDate,
        int progress
        )
    {
        Id = id;
        ParentId = parentId;
        Name = name;
        EmployeeName = employeeName;
        StartDate = startDate;
        DueDate = dueDate;
        Progress = progress;
    }
}
csharp
public class EmployeeTaskService {
    public List<EmployeeTask> GenerateData() {
        return new List<EmployeeTask>() {
            new EmployeeTask(1, 0, "Simplify & Clarify Product Messaging", "John Heart", new DateTime(2018, 4, 3), new DateTime(2018, 4, 14), 14),
            new EmployeeTask(2, 1, "Prepare Financial Reports", "Samantha Bright", new DateTime(2018, 4, 3), new DateTime(2018, 4, 7), 17),
            new EmployeeTask(3, 1, "Prepare Marketing Plan", "Arthur Miller", new DateTime(2018, 4, 7), new DateTime(2018, 4, 14), 11),
            new EmployeeTask(4, 0, "Create Action Plan to Improve Customer Engagement", "Robert Reagan", new DateTime(2017, 8, 8), new DateTime(2018, 4, 8), 23),
            new EmployeeTask(5, 4, "Update Personnel Files", "Greta Sims", new DateTime(2017, 8, 8), new DateTime(2017, 10, 18), 100),
            new EmployeeTask(6, 4, "Review Health Insurance Options", "Brett Wade", new DateTime(2017, 9, 27), new DateTime(2017, 11, 10), 37),
            new EmployeeTask(7, 4, "Choose Between PPO and HMO Health Plan", "Sandra Johnson", new DateTime(2017, 12, 13), new DateTime(2018, 3, 23), 17),
            new EmployeeTask(8, 4, "Update Google Adwords Strategy", "Ed Holmes", new DateTime(2017, 8, 23), new DateTime(2017, 12, 23), 45),
            new EmployeeTask(9, 4, "Create New Brochure Design", "Barb Banks", new DateTime(2018, 1, 3), new DateTime(2018, 3, 14), 17),
            new EmployeeTask(10, 4, "Obtain Price Quote for New Brochure", "Kevin Carter", new DateTime(2018, 2, 1), new DateTime(2018, 3, 15), 18),
            new EmployeeTask(11, 4, "Brochure Design Review", "Cindy Stanwick", new DateTime(2017, 8, 22), new DateTime(2017, 10, 28), 4),
            new EmployeeTask(12, 4, "Review Website Redesign Strategy", "Sammy Hill", new DateTime(2017, 9, 16), new DateTime(2018, 3, 6), 73),
            new EmployeeTask(13, 4, "Roll Out New Website", "Davey Jones", new DateTime(2017, 11, 7), new DateTime(2018, 2, 6), 9),
            new EmployeeTask(14, 4, "Update Sales/Marketing Strategy", "Victor Norris", new DateTime(2017, 12, 13), new DateTime(2018, 4, 2), 5),
            new EmployeeTask(15, 4, "Update Sales/Revenue Report", "Mary Stern", new DateTime(2017, 12, 25), new DateTime(2018, 4, 2), 4),
            new EmployeeTask(16, 4, "Direct vs Online Sales Comparison Report", "Robin Cosworth", new DateTime(2018, 1, 2), new DateTime(2018, 3, 20), 14),
            new EmployeeTask(17, 4, "Review Sales Report and Approve Modifications", "Kelly Rodriguez", new DateTime(2017, 9, 4), new DateTime(2017, 10, 30), 8),
            new EmployeeTask(18, 4, "Update R&D Strategy", "James Anderson", new DateTime(2017, 11, 13), new DateTime(2017, 12, 4), 12),
            new EmployeeTask(19, 4, "Discuss Updated R&D Strategy", "Antony Remmen", new DateTime(2017, 10, 29), new DateTime(2017, 12, 31), 14),
            new EmployeeTask(20, 4, "Update QA Strategy", "Olivia Peyton", new DateTime(2017, 10, 31), new DateTime(2017, 11, 2), 18),
            new EmployeeTask(21, 4, "Schedule Training Events", "Taylor Riley", new DateTime(2017, 11, 19), new DateTime(2018, 4, 7), 21),
            new EmployeeTask(22, 4, "Approve Hiring of John Jeffers", "Amelia Harper", new DateTime(2018, 1, 7), new DateTime(2018, 4, 8), 10),
            new EmployeeTask(23, 0, "Increase Average Subscription Price", "Wally Hobbs", new DateTime(2017, 8, 9), new DateTime(2017, 9, 13), 96),
            new EmployeeTask(24, 23, "Update Non-Compete Agreements", "Brad Jameson", new DateTime(2017, 8, 9), new DateTime(2017, 9, 3), 96),
            new EmployeeTask(25, 23, "Update Employee Records with New NDA", "Karen Goodson", new DateTime(2017, 8, 23), new DateTime(2018, 9, 10), 100)
        };
    }
}
csharp
// ...
builder.Services.AddSingleton<EmployeeTaskService>();

The PageSize property is not in effect if the ShowAllRows or VirtualScrollingEnabled property is set to true.

Display All Data Rows on a Page

Set the ShowAllRows property to true to display all data rows on one page. If content height exceeds the size of the component itself, the TreeList displays a vertical scrollbar. If the size of the component is not limited, DxTreeList enlarges to fit all rows.

css
.my-class {
    height: 200px;
}
razor
<DxTreeList Data="TreeListData"
            KeyFieldName="Id"
            ParentKeyFieldName="ParentId"
            CssClass="my-class"
            ShowAllRows="true">
    <Columns>
        <DxTreeListDataColumn FieldName="Name" Caption="Task" />
        <DxTreeListDataColumn FieldName="EmployeeName" />
        <DxTreeListDataColumn FieldName="StartDate" />
        <DxTreeListDataColumn FieldName="DueDate" />
    </Columns>
</DxTreeList>

This mode can cause performance issues if the TreeList component is bound to a large data source. In this case, turn on the VirtualScrollingEnabled option. In virtual scrolling mode, the TreeList component renders only rows visible within the viewport and several rows above and below that range.

Pager UI

The TreeList component displays a pager below data rows. You can use the PagerPosition property to show the pager at the top of the TreeList or both at the top and bottom.

razor
<DxTreeList Data="TreeListData"
            KeyFieldName="Id"
            ParentKeyFieldName="ParentId"
            PageSize="4"
            PagerPosition="TreeListPagerPosition.TopAndBottom">
    <Columns>
        <DxTreeListDataColumn FieldName="Name" Caption="Task" />
        <DxTreeListDataColumn FieldName="EmployeeName" />
        <DxTreeListDataColumn FieldName="StartDate" />
        <DxTreeListDataColumn FieldName="DueDate" />
    </Columns>
</DxTreeList>

Use the PagerNavigationMode property to specify how users navigate among pages. The following values are available:

InputBox

The pager displays an input box. Users can enter the desired page number within it.

NumericButtons

The pager displays numeric buttons.

You can use the following properties to customize this mode:

PagerVisibleNumericButtonCountSpecifies the maximum number of numeric buttons displayed in the pager.PagerAutoHideNavButtonsSpecifies whether arrow navigation buttons are hidden when all numeric buttons are displayed in the pager.

razor
<DxTreeList Data="TreeListData"
            KeyFieldName="Id"
            ParentKeyFieldName="ParentId"
            PagerNavigationMode="PagerNavigationMode.NumericButtons"
            PagerVisibleNumericButtonCount="15"
            PagerAutoHideNavButtons="true" >
    <Columns> ... </Columns>
</DxTreeList>

Auto(Default value). If the TreeList is displayed on small devices or the number of pages is greater than or equal to the PagerSwitchToInputBoxButtonCount value, the pager displays an input box. Otherwise, numeric buttons are displayed.

The TreeList component includes built-in keyboard shortcuts that allow you to navigate between pages. Refer to the following help topic for additional information: Keyboard Support in Blazor TreeList.

Page Size Selector

The TreeList allows users to change the page size dynamically at runtime. To display the page size selector, enable the PageSizeSelectorVisible option. Use the PageSizeSelectorItems property to specify predefined page sizes available in a drop-down list. You can also enable the PageSizeSelectorAllRowsItemVisible option to display all TreeList rows on one page (the All drop-down item).

razor
<DxTreeList Data="TreeListData"
            KeyFieldName="Id"
            ParentKeyFieldName="ParentId" 
            PageSizeSelectorVisible="true"
            PagerPosition="TreeListPagerPosition.Top"
            PageSizeSelectorItems="@(new int[] { 5, 10, 15 })"
            PageSizeSelectorAllRowsItemVisible="true" >
    <Columns>
        <DxTreeListDataColumn FieldName="Name" Caption="Task" />
        <DxTreeListDataColumn FieldName="EmployeeName" />
        <DxTreeListDataColumn FieldName="StartDate" />
        <DxTreeListDataColumn FieldName="DueDate" />
    </Columns>
</DxTreeList>

The PageIndex property identifies the active page. Use this property to switch between pages in code. When the active page changes, the PageIndexChanged event fires. To get the total number of TreeList pages, call the GetPageCount() method.

razor
<DxTreeList Data="TreeListData"
            KeyFieldName="Id"
            ParentKeyFieldName="ParentId"
            PageIndex="@TreeListPageIndex"
            PageIndexChanged="OnPageIndexChanged">
    <Columns>
        <DxTreeListDataColumn FieldName="Name" Caption="Task" />
        <DxTreeListDataColumn FieldName="EmployeeName" />
        <DxTreeListDataColumn FieldName="StartDate" />
        <DxTreeListDataColumn FieldName="DueDate" />
    </Columns>
</DxTreeList>

@code {
    // ...
    int TreeListPageIndex { get; set; }

    void OnPageIndexChanged(int newPageIndex) {
        TreeListPageIndex = newPageIndex;
        // ...
    }
}

You can call the following methods to navigate to a specific row:

MakeRowVisible(Int32)Makes the row with the specified visible index visible on screen.SetFocusedRowIndex(Int32)Moves focus to the row with the specified visible index.

If the specified row is on another page, the TreeList component navigates to that page and updates the PageIndex property. Otherwise, the component scrolls data up or down until the row appears.

csharp
void ScrollToLastRow() {
    TreeList.MakeRowVisible(TreeList.GetVisibleRowCount() - 1);
}

Save and Restore Paging Settings

The TreeList allows you to save its layout between application work sessions. The saved information includes paging settings that users can change: current page number, page size. Refer to the following topic for additional information: TreeListPersistentLayout.

Hide the Pager

Set the PagerVisible property to false to hide the built-in pager. Note that the TreeList component hides the pager when the ShowAllRows or VirtualScrollingEnabled property is set to true.

This section contains a comprehensive paging-related API reference.

Show API Reference

DxTreeList API memberTypeDescription
PageIndexPropertySpecifies the active page index.
PagerAutoHideNavButtonsPropertySpecifies whether arrow navigation buttons are hidden when all numeric buttons are displayed in the pager.
PagerNavigationModePropertySpecifies how users navigate between TreeList pages.
PagerPositionPropertySpecifies the pager position.
PagerSwitchToInputBoxButtonCountPropertySpecifies the total number of pages when the pager switches from numeric buttons to the input box in Auto mode.
PagerVisiblePropertySpecifies whether the TreeList displays the pager.
PagerVisibleNumericButtonCountPropertySpecifies the maximum number of numeric buttons displayed in the pager.
PageSizePropertySpecifies the maximum number of rows displayed on a page.
PageSizeSelectorAllRowsItemVisiblePropertySpecifies whether the page size selector contains the All item.
PageSizeSelectorItemsPropertySpecifies items available in the page size selector.
PageSizeSelectorVisiblePropertySpecifies whether the TreeList displays the page size selector in the pager.
ShowAllRowsPropertySpecifies whether the TreeList displays all rows on one page. To avoid performance issues when the TreeList is bound to a large data source, use the VirtualScrollingEnabled property instead.
GetPageCount()MethodReturns the total number of pages in the TreeList.
GetVisibleRowCount()MethodReturns the total number of visible rows in the TreeList.
PageIndexChangedEventFires when the TreeList’s active page index changes.
PageSizeChangedEventFires when the page size changes.

Task-Based Examples

This section contains code samples that demonstrate data paging functionality.

Display Total Number of Visible Records (Custom Pager)

The TreeList component does not support a template for the pager. If you want to display custom content in the pager area, set the PagerVisible property to false to hide the default pager and organize your own components for navigation in an external container.

In the following code snippet, an external <div> displays the total number of records next to a custom DxPager component:

css
.treelist-container {
    width: 950px;
}
.pager-container {
    display: flex;
    justify-content: space-between;
    padding: 8px;
    border: 1px solid #d2d2d2;
    border-top: none;
}
razor
<div class="treelist-container">
    <DxTreeList @ref="@TreeList"
                Data="@TreeListData"
                KeyFieldName="Id"
                ParentKeyFieldName="ParentId"
                @bind-PageIndex="@ActivePageIndex"
                PagerVisible="false"
                PageSize="@PageSize"
                FooterDisplayMode="TreeListFooterDisplayMode.Never">
        <Columns>
            <DxTreeListDataColumn FieldName="Name" Caption="Task" />
            <DxTreeListDataColumn FieldName="EmployeeName" />
            <DxTreeListDataColumn FieldName="StartDate" />
            <DxTreeListDataColumn FieldName="DueDate" />
        </Columns>
        <TotalSummary>
            <DxTreeListSummaryItem SummaryType="TreeListSummaryItemType.Count"
                                   FieldName="@RowCountField"
                                   Visible="false" />
        </TotalSummary>
    </DxTreeList>
    <div class="pager-container">
        <DxPager PageCount="@PageCount" @bind-ActivePageIndex="@ActivePageIndex" />
        <div>
            Total: @TotalRecords records
        </div>
    </div>
</div>

@code {
    ITreeList TreeList { get; set; }
    List<EmployeeTask> TreeListData { get; set; }
    int PageCount { get; set; }
    int TotalRecords { get; set; }
    int PageSize { get; set; } = 5;
    int ActivePageIndex { get; set; } = 0;
    string RowCountField { get; set; } = "DueDate";

    protected override void OnInitialized() {
        TreeListData = EmployeeTaskService.GenerateData();
    }
    protected override void OnAfterRender(bool firstRender) {
        TotalRecords = (int)(TreeList.GetTotalSummaryValue(TreeList?.GetTotalSummaryItems().First()));
        PageCount = (int)Math.Ceiling((decimal)TotalRecords / PageSize);
        StateHasChanged();
        base.OnAfterRender(firstRender);
    }
}