Blazor Contacts组件分页异常:SetPage方法接收错误页码值
Blazor分页组件点击页码始终触发最后一页的问题解决
问题现象
开发的Contacts Blazor组件分页功能异常:点击任意页码按钮(比如第2页),SetPage方法接收到的参数始终是最后一页的数值(如示例中的6),问题出在分页控件的for循环逻辑中。
原因分析
分页for循环里的@onclick="() => SetPage(i)"使用lambda表达式捕获了循环变量i的引用,而非每次迭代的具体数值。当循环执行完毕,所有按钮的点击事件都会使用i的最终值(即最后一页的页码),导致点击任意页码都跳转到最后一页。
解决方案
在for循环内部,将当前迭代的i值赋值给一个局部变量,让lambda捕获这个局部变量而非循环变量i。这样每个页码按钮的点击事件都会绑定当前迭代的正确页码值。
修正后的分页代码片段
<!-- Pagination Controls --> <ul class="pagination mb-0"> <li class="page-item @(CurrentPage == 1 ? "disabled" : "")"> <button class="page-link" @onclick="() => SetPage(CurrentPage - 1)" disabled="@((CurrentPage == 1))">Previous</button> </li> @for (int i = 1; i <= TotalPages; i++) { // 创建局部变量存储当前页码 var page = i; <li class="page-item @(CurrentPage == page ? "active" : "")"> <button class="page-link" @onclick="() => SetPage(page)">@page</button> </li> } <li class="page-item @(CurrentPage == TotalPages ? "disabled" : "")"> <button class="page-link" @onclick="() => SetPage(CurrentPage + 1)" disabled="@((CurrentPage == TotalPages))">Next</button> </li> </ul>
完整修正后的组件代码
@page "/Contacts" @rendermode InteractiveServer <h3>Contacts Component</h3> <!-- Search Bar --> <div class="row mb-3"> <div class="col-md-6"> <input type="text" class="form-control" placeholder="Search contacts..." @bind="SearchTerm" @bind:event="oninput" /> </div> </div> <!-- Table with Sorting --> <table class="table table-striped"> <thead> <tr> <th @onclick="() => SortByColumn(nameof(Contact))">Contact @GetSortIcon(nameof(Contact))</th> </tr> </thead> <tbody> @foreach (var contact in PagedContacts) { <tr> <td> <button class="btn btn-link" @onclick="() => SelectContact(contact)">@contact</button> </td> </tr> } </tbody> </table> <!-- Pagination --> <nav class="d-flex justify-content-between align-items-center"> <!-- Page Label --> <span>Page @CurrentPage of @TotalPages (@FilteredContacts.Count() total records)</span> <!-- Pagination Controls --> <ul class="pagination mb-0"> <li class="page-item @(CurrentPage == 1 ? "disabled" : "")"> <button class="page-link" @onclick="() => SetPage(CurrentPage - 1)" disabled="@((CurrentPage == 1))">Previous</button> </li> @for (int i = 1; i <= TotalPages; i++) { var page = i; <li class="page-item @(CurrentPage == page ? "active" : "")"> <button class="page-link" @onclick="() => SetPage(page)">@page</button> </li> } <li class="page-item @(CurrentPage == TotalPages ? "disabled" : "")"> <button class="page-link" @onclick="() => SetPage(CurrentPage + 1)" disabled="@((CurrentPage == TotalPages))">Next</button> </li> </ul> </nav> @code { [Parameter] public List<string> ContactsList { get; set; } = new(); [Parameter] public EventCallback<(string ContactName, string FieldName)> OnContactSelected { get; set; } [Parameter] public string TargetField { get; set; } = string.Empty; private string _searchTerm = ""; private string SortColumn = nameof(Contact); private bool SortAscending = true; private int CurrentPage = 1; private int PageSize = 5; // 修正搜索属性的递归引用问题 private string SearchTerm { get => _searchTerm; set { if (_searchTerm != value) { _searchTerm = value; CurrentPage = 1; // 搜索时重置到第一页 } } } private void SortByColumn(string column) { if (SortColumn == column) { SortAscending = !SortAscending; } else { SortColumn = column; SortAscending = true; } } private void SetPage(int page) { CurrentPage = page; } // 过滤、排序后的联系人列表 private IEnumerable<string> FilteredContacts => ContactsList .Where(c => string.IsNullOrEmpty(SearchTerm) || c.Contains(SearchTerm, StringComparison.OrdinalIgnoreCase)) .OrderBy(c => SortAscending ? c : null) .ThenByDescending(c => SortAscending ? null : c); // 分页后的联系人列表 private IEnumerable<string> PagedContacts => FilteredContacts .Skip((CurrentPage - 1) * PageSize) .Take(PageSize); private int TotalPages => (int)Math.Ceiling(FilteredContacts.Count() / (double)PageSize); protected override void OnParametersSet() { Console.WriteLine($"CurrentPage: {CurrentPage}, TotalPages: {TotalPages}"); Console.WriteLine($"FilteredContacts Count: {FilteredContacts.Count()}, PagedContacts Count: {PagedContacts.Count()}"); } private async Task SelectContact(string contact) { if (OnContactSelected.HasDelegate) { await OnContactSelected.InvokeAsync((contact, TargetField)); } } private string GetSortIcon(string column) { if (SortColumn == column) { return SortAscending ? "▲" : "▼"; } return string.Empty; } public class Contact { public string Name { get; set; } public string Email { get; set; } public string Phone { get; set; } } }
补充说明
原代码中_searchTerm属性存在递归引用问题(get返回自身),会导致栈溢出,已在修正代码中修复为正确的属性定义,确保搜索时能正常重置页码。
内容的提问来源于stack exchange,提问作者Rod
相关产品推荐
相关产品推荐

