.net core 在Blazor中筛选分页列表
我有一个Blazor应用程序,其中有一个列表中的对象列表。我设置了一个寻呼机组件(如下所示),它工作得很好。然后在列表中的一组字段上设置搜索框功能。如果寻呼机在第一页,所有这些都非常有效。任何其他页面和搜索都会显示不可预测的结果。有时甚至无法正确筛选该页面上的项目。任何建议都会有帮助。谢谢 Pager.razor.net core 在Blazor中筛选分页列表,.net-core,blazor-server-side,.net Core,Blazor Server Side,我有一个Blazor应用程序,其中有一个列表中的对象列表。我设置了一个寻呼机组件(如下所示),它工作得很好。然后在列表中的一组字段上设置搜索框功能。如果寻呼机在第一页,所有这些都非常有效。任何其他页面和搜索都会显示不可预测的结果。有时甚至无法正确筛选该页面上的项目。任何建议都会有帮助。谢谢 Pager.razor @typeparam TItem <div class="row d-flex col-9"> <div class="justify-content-center
@typeparam TItem
<div class="row d-flex col-9">
<div class="justify-content-center">
@if (PageCount > 1 && List.Count > PageSize)
{
<ul class="pagination justify-content-center">
<li><button @onclick="@(() => ChangePage(1))" class="btn">«</button></li>
@for (var i = StartIndex; i <= FinishIndex; i++)
{
var currentIndex = i;
@if (i == CurrentPage)
{
<li class="page-item active"><span class="btn">@i</span></li>
}
else
{
<li class="page-item"><button class="btn page-link" @onclick="@(() => ChangePage(currentIndex))">@i</button></li>
}
}
<li><button @onclick="@(() => ChangePage(PageCount))" class="btn">»</button></li>
</ul>
}
</div>
<select class="custom-select offset-1 col-1 ml-auto" bind="@PageSize" @onchange="@(e => ChangePageSize(e))">
<option value="10">10</option>
<option value="25">25</option>
<option value="50">50</option>
</select>
</div>
@code {
[Parameter]
public List<TItem> List { get; set; }
public List<TItem> Display { get; set; }
[Parameter]
public Action<List<TItem>> DisplayChanged { get; set; }
[Parameter]
public Action<bool> Rendered { get; set; }
private int PageSize { get; set; } = 10;
private int CurrentPage { get; set; } = 1;
private int StartIndex { get; set; }
private int FinishIndex { get; set; }
private int PageCount { get; set; }
protected override void OnAfterRender(bool firstRender)
{
base.OnAfterRender(firstRender);
Rendered?.Invoke(true);
}
private void ChangePageSize(ChangeEventArgs e)
{
PageSize = int.Parse(e.Value.ToString());
ChangePage(1);
}
private void ChangeDisplay()
{
DisplayChanged?.Invoke(
List
.Skip((CurrentPage - 1) * PageSize)
.Take(PageSize)
.ToList()
);
}
protected override void OnParametersSet()
{
ResetIndex();
ChangeDisplay();
base.OnParametersSet();
}
protected void ChangePage(int page)
{
CurrentPage = page;
ResetIndex();
ChangeDisplay();
}
private void ResetIndex()
{
PageCount = List.Count / PageSize;
if (List.Count % PageSize > 0)
{
PageCount++;
}
StartIndex = Math.Max(CurrentPage - 5, 1);
FinishIndex = Math.Min(CurrentPage + 5, PageCount);
}
}
private void Filter()
{
switch (Property)
{
case "FirstName":
FilteredUsers = Users.Where(u => u.FirstName.ToLower().Contains(SearchTerm.ToLower())).ToList();
break;
case "LastName":
FilteredUsers = Users.Where(u => u.LastName.ToLower().Contains(SearchTerm.ToLower())).ToList();
break;
case "Role":
FilteredUsers = Users.Where(u => u.Role.ToString().ToLower().Contains(SearchTerm.ToLower())).ToList();
break;
case "Property":
if (string.IsNullOrEmpty(SearchTerm))
{
FilteredUsers = Users;
}
else
{
FilteredUsers = Users.Where(u => TicketingRosters.Any(t => t.Property.PropertyName.ToLower().Contains(SearchTerm.ToLower()) && u.UserId == t.SellerId)).ToList();
}
break;
}
StateHasChanged();
}
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Threading.Tasks;
namespace TicketingSolutions.Models
{
[Table("TicketingRosters")]
public class TicketingRoster : IValidatableObject
{
[Key]
public long TicketingRosterId { get; set; }
public int PropertyId { get; set; }
public Property Property { get; set; }
public long SellerId { get; set; }
public User Seller { get; set; }
public bool IsActive { get; set; }
public DateTime ValidFrom { get; set; }
public DateTime? ValidTo { get; set; }
public DateTime CreatedOn { get; set; }
public long CreatedBy { get; set; }
public DateTime ModifiedOn { get; set; }
public long ModifiedBy { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (ValidTo <= ValidFrom)
{
yield return new ValidationResult("ValidTo cannot be set to a date before or equal to ValidFrom", new[] { nameof(ValidTo) });
}
}
}
}
编辑
以下是您可能要查找的其他函数和属性:
private List<UserDto> Users { get; set; }
private List<UserDto> FilteredUsers { get; set; }
private List<UserDto> Display { get; set; }
private bool IsPagerRendered { get; set; }
private void DisplayChanged(List<UserDto> display)
{
Display = display;
}
private void PagerRendered(bool rendered)
{
IsPagerRendered = rendered;
StateHasChanged();
}
票务名册
@typeparam TItem
<div class="row d-flex col-9">
<div class="justify-content-center">
@if (PageCount > 1 && List.Count > PageSize)
{
<ul class="pagination justify-content-center">
<li><button @onclick="@(() => ChangePage(1))" class="btn">«</button></li>
@for (var i = StartIndex; i <= FinishIndex; i++)
{
var currentIndex = i;
@if (i == CurrentPage)
{
<li class="page-item active"><span class="btn">@i</span></li>
}
else
{
<li class="page-item"><button class="btn page-link" @onclick="@(() => ChangePage(currentIndex))">@i</button></li>
}
}
<li><button @onclick="@(() => ChangePage(PageCount))" class="btn">»</button></li>
</ul>
}
</div>
<select class="custom-select offset-1 col-1 ml-auto" bind="@PageSize" @onchange="@(e => ChangePageSize(e))">
<option value="10">10</option>
<option value="25">25</option>
<option value="50">50</option>
</select>
</div>
@code {
[Parameter]
public List<TItem> List { get; set; }
public List<TItem> Display { get; set; }
[Parameter]
public Action<List<TItem>> DisplayChanged { get; set; }
[Parameter]
public Action<bool> Rendered { get; set; }
private int PageSize { get; set; } = 10;
private int CurrentPage { get; set; } = 1;
private int StartIndex { get; set; }
private int FinishIndex { get; set; }
private int PageCount { get; set; }
protected override void OnAfterRender(bool firstRender)
{
base.OnAfterRender(firstRender);
Rendered?.Invoke(true);
}
private void ChangePageSize(ChangeEventArgs e)
{
PageSize = int.Parse(e.Value.ToString());
ChangePage(1);
}
private void ChangeDisplay()
{
DisplayChanged?.Invoke(
List
.Skip((CurrentPage - 1) * PageSize)
.Take(PageSize)
.ToList()
);
}
protected override void OnParametersSet()
{
ResetIndex();
ChangeDisplay();
base.OnParametersSet();
}
protected void ChangePage(int page)
{
CurrentPage = page;
ResetIndex();
ChangeDisplay();
}
private void ResetIndex()
{
PageCount = List.Count / PageSize;
if (List.Count % PageSize > 0)
{
PageCount++;
}
StartIndex = Math.Max(CurrentPage - 5, 1);
FinishIndex = Math.Min(CurrentPage + 5, PageCount);
}
}
private void Filter()
{
switch (Property)
{
case "FirstName":
FilteredUsers = Users.Where(u => u.FirstName.ToLower().Contains(SearchTerm.ToLower())).ToList();
break;
case "LastName":
FilteredUsers = Users.Where(u => u.LastName.ToLower().Contains(SearchTerm.ToLower())).ToList();
break;
case "Role":
FilteredUsers = Users.Where(u => u.Role.ToString().ToLower().Contains(SearchTerm.ToLower())).ToList();
break;
case "Property":
if (string.IsNullOrEmpty(SearchTerm))
{
FilteredUsers = Users;
}
else
{
FilteredUsers = Users.Where(u => TicketingRosters.Any(t => t.Property.PropertyName.ToLower().Contains(SearchTerm.ToLower()) && u.UserId == t.SellerId)).ToList();
}
break;
}
StateHasChanged();
}
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Threading.Tasks;
namespace TicketingSolutions.Models
{
[Table("TicketingRosters")]
public class TicketingRoster : IValidatableObject
{
[Key]
public long TicketingRosterId { get; set; }
public int PropertyId { get; set; }
public Property Property { get; set; }
public long SellerId { get; set; }
public User Seller { get; set; }
public bool IsActive { get; set; }
public DateTime ValidFrom { get; set; }
public DateTime? ValidTo { get; set; }
public DateTime CreatedOn { get; set; }
public long CreatedBy { get; set; }
public DateTime ModifiedOn { get; set; }
public long ModifiedBy { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (ValidTo <= ValidFrom)
{
yield return new ValidationResult("ValidTo cannot be set to a date before or equal to ValidFrom", new[] { nameof(ValidTo) });
}
}
}
}
使用系统;
使用System.Collections.Generic;
使用System.ComponentModel.DataAnnotations;
使用System.ComponentModel.DataAnnotations.Schema;
使用System.Linq;
使用System.Threading.Tasks;
名称空间TicketingSolutions.Models
{
[表格(“票务名册”)]
公共类票务花名册:IValidatableObject
{
[关键]
公共长票证名册ID{get;set;}
公共int属性ID{get;set;}
公共属性{get;set;}
公共长SellerId{get;set;}
公共用户卖方{get;set;}
公共bool IsActive{get;set;}
public DateTime ValidFrom{get;set;}
公共日期时间?有效到{get;set;}
public DateTime CreatedOn{get;set;}
public long CreatedBy{get;set;}
公共日期时间修饰符{get;set;}
public long ModifiedBy{get;set;}
公共IEnumerable验证(ValidationContext ValidationContext)
{
if(ValidTo有点难理解,因为有一些外部方法在本例中没有显示(编辑可能是为了清晰?)但是,您似乎在使用寻呼机.razor之外的东西来指示分页的工作方式。赠品是DisplayChanged
事件回调。我可以建议您通过消除顾虑来解决这个问题,这样您就可以让一切正常工作。(根据您拥有的,我可以让它运行得相当快)
首先,让我们设置寻呼机,使其只处理分页信息,并在一个自包含、可重用的组件中包含它自己的所有逻辑。给它一个TItem
列表和一个RenderFragment
,它知道该做什么
@typeparam-TItem
@如果(列表!=null)
{
@foreach(显示列表中的变量项)
{
@儿童内容(项目)
}
}
@如果(PageCount>1&&List.Count>PageSize)
{
…这里什么都没有改变,为了简洁起见被删除了。。。
}
10
25
50
@代码{
[参数]
公共列表{get;set;}
public List DisplayList{get;set;}=new List();
[参数]
公共RenderFragment ChildContent{get;set;}
//[参数]
//公共操作DisplayChanged{get;set;}
//[参数]
//呈现的公共操作{get;set;}
私有int PageSize{get;set;}=10;
private int CurrentPage{get;set;}=1;
私有int StartIndex{get;set;}
私有int FinishIndex{get;set;}
private int PageCount{get;set;}
//受保护的覆盖无效OnAfterRender(布尔firstRender)
//{
//base.OnAfterRender(firstRender);
//呈现?.Invoke(真);
//}
私有void ChangePageSize(changeventargs e)
{
PageSize=int.Parse(例如Value.ToString());
更改页面(1);
}
私有void changesplay()
{
显示列表=列表
.Skip((当前页面-1)*页面大小)
.Take(页面大小)
.ToList();
}
受保护的覆盖无效OnParametersSet()
{
//编辑
更改页面(1);
}
受保护的无效更改页(整版页)
{
当前页面=第页;
重置索引();
ChangeDisplay();
}
私有void ResetIndex()
{
PageCount=List.Count/PageSize;
如果(List.Count%PageSize>0)
{
PageCount++;
}
StartIndex=Math.Max(当前第5页,第1页);
FinishIndex=Math.Min(当前页面+5,页面计数);
}
}
您将看到@code块中的一些内容被注释掉了。您不需要这些内容来实现此功能。我们将在一分钟后在父组件中处理初始列表中的值。您将看到一个RenderFragment
参数,以及一个非参数的DisplayList
的新属性。您还会注意到在marku中p、 我们有一个@foreach
块为DisplayList
属性中的每个项目呈现一个RenderFragment
实例。如果您遵循onparameters set
方法的逻辑和您的处理程序来单击页码和箭头,您将看到我们正在创建和呈现的子列表ode>List
参数,该参数基于页数和页码,这就是所呈现的全部内容。该组件现在负责对给定列表中的项目进行分页,并且除了要呈现的列表之外,它没有要运行的外部依赖项,以及关于如何以RenderFragment
的形式呈现每个项目的说明
接下来,在父组件中,我们设置对寻呼机的调用,如下所示:
@context.FirstName@context.LastName在@context.Role中
您可以随意设置,我使用了
标记进行说明,但如果您需要更深入的信息,请按照说明创建表格、列表等。该组件现在接受
标记之间的子内容,并为其自己的分页列表中的每个项目呈现1
到目前为止,我们已经将寻呼机的逻辑与页面的其余部分解耦,因此现在它只是一个渲染工具,而寻呼机的逻辑是内部的。现在我们可以将重点放在过滤和伪造上