Blazor组件分页

5

我正在开发Blazor应用程序,其中有一个组件显示记录列表(从实体框架实体检索),想知道在该组件上实现分页的最佳和最简单的方法是什么。

任何帮助都将不胜感激。

3个回答

6

在Blazor中,您可以完全控制DOM。由于您正在使用EF,因此可以轻松执行Skip和Take进行分页:

private int pageSize = 100;
private int pageNumber = 1;   

在 HTML 中:

for(int p = 1; p<= list.Count() / pageSize ; p++) {
<button type="button" @onclick="(e=>HandleChangePage(p))">@p</button>
}

处理更改页面:

void HandleChangePage(int p) {
  pageNumber  = p;
  var page = list.Skip((p-1) * pageSize).Take(pageSize);
}

这是最简单的分页方式,
现在您可以创建您的分页列表组件
现在您需要将您的列表作为参数传递给组件

[Parameter]
public List<ClassName> list {get;set;}

如果你想使用通用列表,请查看模板上下文参数

1
我不确定为什么会发生这种情况,但将p传递给HandleChangePage时,它总是完全递增的值。我必须分配一个新的int并传递它以解决这个问题,就像这样:int pageId = p; @onclick(() => HandleChangePage(pageId)) - GeorgiG
@GeorgiG 请参见 https://github.com/dotnet/aspnetcore/issues/10138 - Stef Heyenrath
而不是使用list.Count() / pageSize,你应该使用Convert.ToInt32(Math.Ceiling(list.Count() / Convert.ToDecimal(pageSize))) - Stef Heyenrath

6
在Blazor中,您可以像在MVC中一样传递您的页面。对于一个非常简单的示例,请按照以下方式更改FetchData.razor:
@page "/fetchdata"
@page "/fetchdata/{PageNumber:int}"

... the HTML for the table...

<div>
    @for (int i = 1; i <= 5; i++)
    {
        <span><a href="fetchdata/@i"> @i </a>|</span>         
    }
</div>

@code {

    [Parameter]
    public int PageNumber { get; set; }

    private WeatherForecast[] forecasts;

    protected override async Task OnParametersSetAsync()
    {
        if (PageNumber < 1) PageNumber = 1;

        // adapt the service to take pageIndex, pageSize
        forecasts = await ForecastService.GetForecastAsync(PageNumber-1, 5);
    }
}

分页器非常简单,仅有1..5。有一些可用的组件可以完成大多数标记和逻辑,可以在谷歌上搜索“Blazor分页器组件”。我很快找到了这个


1
感谢Henk Holterman和Ali Borjian,我尝试了两种解决方案的组合,它像魔术一样奏效了。 - ZKS

5

我开发了一个通用的分页组件,它使用HTML表格并且易于重复使用。请将其保存在自己的组件razor中,命名为PagedList.razor:

@typeparam TItem

@if (!ListQuery.Any())
{
  <div class="none-indicator">(none)</div>
}
else
{
  @if (TotalPages() > 1)
  {
    <div class="pager-display">
      @if (CurrentPage == 1)
      {
        <button disabled>&laquo;</button>
        <button disabled>&lsaquo;</button>
      }
      else
      {
        <button @onclick="@MoveFirst" title="Move First">&laquo;</button>
        <button @onclick="@MoveBack" title="Move Back">&lsaquo;</button>
      }
      <span>@CurrentPage of @TotalPages() </span>
      @if (!AtLastPage())
      {
        <button @onclick="@MoveNext" title="Move Next">&rsaquo;</button>
        <button @onclick="@MoveLast" title="Move Last">&raquo;</button>
      }
      else
      {
        <button disabled>&rsaquo;</button>
        <button disabled>&raquo;</button>
      }
    </div>
  }

  <table class="table table-striped">
    <thead>
      @HeaderDisplay
    </thead>
    <tbody>
      @foreach (TItem item in CurrentDisplay)
      {
        @ItemDisplay(item)
      }
    </tbody>
  </table>
}

@code {
  [Parameter]
  public IQueryable<TItem> ListQuery { get; set; }
  [Parameter]
  public RenderFragment HeaderDisplay { get; set; }
  [Parameter]
  public RenderFragment<TItem> ItemDisplay { get; set; }
  [Parameter]
  public int ItemsPerPage { get; set; } = 10;

  private int CurrentPage = 1;
  private List<TItem> CurrentDisplay;
  private int TotalCount;

  protected override void OnParametersSet()
  {
    UpdateDisplay();
    TotalCount = ListQuery.Count();
  }

  private void UpdateDisplay()
  {
    CurrentDisplay = ListQuery.Skip((CurrentPage - 1) * ItemsPerPage).Take(ItemsPerPage).ToList();
  }

  private bool AtLastPage()
  {
    return CurrentPage >= TotalPages();
  }

  private int TotalPages()
  {
    return Convert.ToInt32(Math.Ceiling(TotalCount / Convert.ToDecimal(ItemsPerPage)));
  }

  private void MoveFirst()
  {
    CurrentPage = 1;
    UpdateDisplay();
  }

  private void MoveBack()
  {
    CurrentPage--;
    UpdateDisplay();
  }

  private void MoveNext()
  {
    CurrentPage++;
    UpdateDisplay();
  }

  private void MoveLast()
  {
    CurrentPage = TotalPages();
    UpdateDisplay();
  }

}

以下是使用示例:

这是一个使用示例:

<PagedList ListQuery="People">
  <HeaderDisplay>
    <tr>
      <th></th>
      <th>First Name</th>
      <th>Last Name</th>
      <th>Title</th>
    </tr>
  </HeaderDisplay>
  <ItemDisplay>
    <tr>
      <td><a href="People/Edit/@(context.ID)">Edit</a></td>
      <td>@context.FirstName</td>
      <td>@context.LastName</td>         
      <td>@context.Title</td>
    </tr>
  </ItemDisplay>
</PagedList>

@code {
  private IQueryable<Person> People;

  protected override void OnInitialized()
  {
    People = DatabaseContext.Person.Where(p => ...)
  }
}

1
你在客户端代码中直接使用DatabaseContext,从“安全性”的角度来看,这可能是一个问题,对吗? - MarchalPT
微软并未提到这是一个问题:https://learn.microsoft.com/en-us/aspnet/core/blazor/blazor-server-ef-core?view=aspnetcore-5.0 - Rono
1
如果这是在客户端之间共享的,那么客户端可以更改,并且他们可以访问上下文以删除条目等。 - MarchalPT
如果您能提供一篇解释这个问题的文章链接,我很有兴趣看看。 - Rono

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接