Maison  >  Article  >  développement back-end  >  Pagination des données DataList et Repeater

Pagination des données DataList et Repeater

高洛峰
高洛峰original
2017-02-08 09:18:041445parcourir

Introduction

La pagination et le tri sont des fonctions fréquemment utilisées lors de l'affichage des données. Par exemple, lorsque vous recherchez des livres sur ASP.NET dans une librairie en ligne, vous pouvez obtenir des centaines ou des milliers de résultats, mais seuls dix éléments sont répertoriés sur chaque page. Et les résultats peuvent être triés par titre (titre du livre), prix (prix), nombre de pages (nombre de pages), nom de l'auteur (auteur), etc. Comme nous l'avons discuté dans Pagination et tri des données du rapport, GridView, DetailsView et FormView ont tous une fonctionnalité de pagination intégrée, qui peut être activée en cochant simplement une case. GridView prend également en charge le tri intégré.

Malheureusement, ni DataList ni Repeater ne fournissent de fonctionnalités intégrées de pagination et de tri. Dans ce chapitre, nous apprendrons comment ajouter la prise en charge de la pagination et du tri à DataList et Repeater. Nous devons créer une interface de pagination, afficher l'enregistrement de page correct et enregistrer la page consultée pendant le processus de publication. Bien que cela prenne plus de temps et écrive plus de code que GridView, DetailsView et FormView, cela offre également plus d'évolutivité.

Remarque : ce chapitre se concentre sur la pagination, et dans le chapitre suivant, nous apprendrons le tri.

Étape 1 : Ajouter les pages du didacticiel de pagination et de tri

Ajoutez d'abord les pages nécessaires à ce chapitre et au chapitre suivant. Créez un dossier appelé PagingSortingDataListRepeater et ajoutez les 5 pages suivantes, en n'oubliant pas de sélectionner Site.master pour toutes.

Default.aspx
Paging.aspx
Sorting.aspx
SortingWithDefaultPaging.aspx
SortingWithCustomPaging.aspx

Pagination des données DataList et Repeater

Figure 1 : Créer une page

Ensuite, ouvrez la page Default.aspx et faites glisser un contrôle utilisateur SectionLevelTutorialListing.ascx depuis le dossier UserControls. Nous avons utilisé ce contrôle utilisateur à plusieurs reprises. Voir Pages maîtres et navigation sur le site .

Pagination des données DataList et Repeater

Figure 2 : Ajout de contrôles utilisateur

Afin de lister les tutoriels de tri et de pagination, nous devons les ajouter au plan du site. Ouvrez le fichier Web.sitemap et ajoutez le langage de balisage suivant après le nœud « Modification et suppression avec la DataList » () :

<siteMapNode
 url="~/PagingSortingDataListRepeater/Default.aspx"
 title="Paging and Sorting with the DataList and Repeater"
 description="Paging and Sorting the Data in the DataList and Repeater Controls">
 <siteMapNode
  url="~/PagingSortingDataListRepeater/Paging.aspx"
  title="Paging"
  description="Learn how to page through the data shown
      in the DataList and Repeater controls." />
 <siteMapNode
  url="~/PagingSortingDataListRepeater/Sorting.aspx"
  title="Sorting"
  description="Sort the data displayed in a DataList or
      Repeater control." />
 <siteMapNode
  url="~/PagingSortingDataListRepeater/SortingWithDefaultPaging.aspx"
  title="Sorting with Default Paging"
  description="Create a DataList or Repeater control that is paged using
      default paging and can be sorted." />
 <siteMapNode
  url="~/PagingSortingDataListRepeater/SortingWithCustomPaging.aspx"
  title="Sorting with Custom Paging"
  description="Learn how to sort the data displayed in a DataList or
      Repeater control that uses custom paging." />
</siteMapNode>

Pagination des données DataList et Repeater

Figure 3 : Mettre à jour le plan du site

Revoir la pagination

Plus tôt, nous avons appris à utiliser GridView, DetailsView et FormView pour paginer. Ces trois contrôles fournissent tous une fonction appelée pagination par défaut. Il vous suffit de cocher « Activer la pagination » sur l'étiquette intelligente. Lors de l'utilisation de la pagination par défaut, chaque fois que des données sont demandées - que ce soit pour la première page ou une autre page - GridView, DetailsView et FormView demanderont à nouveau toutes les données. Les données d'une page particulière sont ensuite affichées en fonction de l'index de page demandé et du nombre d'enregistrements affichés par page, tandis que les autres données (c'est-à-dire les données demandées mais non affichées) sont ignorées. Nous avons discuté en détail de la pagination par défaut dans la section Pagination et tri des données du rapport.

La pagination par défaut demande toutes les données à chaque fois, elle ne convient donc pas lorsqu'il y a une grande quantité de données. Par exemple, imaginez afficher 10 éléments de données par page, pour un total de 50 000 éléments. Chaque fois que l'utilisateur consulte une page, 50 000 données sont demandées à la base de données, et seules 10 d'entre elles sont affichées.

La pagination personnalisée renvoie uniquement les données demandées à chaque fois, résolvant ainsi le problème de performances de la pagination par défaut. Lorsque nous utilisons une pagination personnalisée, nous devons écrire des instructions SQL efficaces qui renvoient les enregistrements corrects. Nous avons appris ici à utiliser le mot-clé ROW_NUMBER() de SQL Server2005 pour créer une telle instruction.

En utilisant la pagination par défaut dans DataList ou Repeater, nous pouvons utiliser la classe PagedDataSource pour envelopper le contenu qui doit être paginé dans ProductsDataTable. La classe PagedDataSource possède une propriété DataSource qui peut être affectée à n'importe quel objet de type énumération, ainsi que PageSize (le nombre d'enregistrements affichés par page) et CurrentPageIndex (l'index de la page actuelle). Une fois ces propriétés définies, PagedDataSource peut être utilisé comme source de données pour n'importe quel contrôle de données. PagedDataSource renvoie les enregistrements appropriés en fonction de PageSize et CurrentPageIndex. La figure 4 décrit les fonctionnalités de la classe PagedDataSource.

Figure 4 : PagedDataSource utilise une interface paginable pour envelopper les objets d'énumération

Les objets PagedDataSource peuvent être créés et configurés directement dans la BLL et liés à DataList ou Repeater via ObjectDataSource. Ou vous pouvez le faire directement dans le code derrière la page ASP.NET. Si nous utilisons cette dernière méthode, nous ne pouvons pas utiliser ObjectDataSource et devons lier les données de pagination au DataList ou au Repeater directement par programme.

  PagedDataSource对象也有支持自定义分页的属性。但是在这里我们将不讨论它,因为我们在ProductsBLL类里已经有一个可以精确的返回需要显示的记录的方法。本章我们将学习如何通过在ProductsBLL类里添加一个返回合适的PagedDataSource对象的方法来实现默认分页。下章我们再讨论自定义分页。

第二步: 在BLL里添加默认的分页方法

  ProductsBLL类里现在有一个返回所有product的方法–GetProducts()–和一个返回特定子集的方法–GetProductsPaged(startRowIndex,maximumRows)。当使用默认分页时,GridView, DetailsView, FormView 使用GetProducts()方法获取所有的product,但是在内部使用PagedDataSource来显示正确的记录子集。在DataList和Repeater里实现同样的功能,我们可以在BLL里创建一个模拟这种行为的方法。

在ProductsBLL里添加一个带两个整型参数的方法,名为GetProductsAsPagedDataSource:

pageIndex – 显示的页的索引,从0开始
pageSize – 每页显示的记录数.

  GetProductsAsPagedDataSource首先从GetProducts()里获取所有的记录。然后创建一个PagedDataSource对象,将CurrentPageIndex和PageSize属性设置为传进来的参数,pageIndex和pageSize。方法的最后返回这个配置过的PagedDataSource。

[System.ComponentModel.DataObjectMethodAttribute
 (System.ComponentModel.DataObjectMethodType.Select, false)]
public PagedDataSource GetProductsAsPagedDataSource(int pageIndex, int pageSize)
{
 // Get ALL of the products
 Northwind.ProductsDataTable products = GetProducts();
 // Limit the results through a PagedDataSource
 PagedDataSource pagedData = new PagedDataSource();
 pagedData.DataSource = products.Rows;
 pagedData.AllowPaging = true;
 pagedData.CurrentPageIndex = pageIndex;
 pagedData.PageSize = pageSize;
 return pagedData;
}

第三步: 在DataList里使用默认分页显示Product

  完成GetProductsAsPagedDataSource方法后,我们现在来创建一个提供默认分页的DataList或Repeater。打开PagingSortingDataListRepeater文件夹下的Paging.aspx页,拖一个DataList进来,将ID设为ProductsDefaultPaging。通过智能标签创建一个名为ProductsDefaultPagingDataSource的ObjectDataSource并用GetProductsAsPagedDataSource方法配置它。

Pagination des données DataList et Repeater

图 5: 创建并配置ObjectDataSource

在UPDATE, INSERT, DELETE 标签的下拉列表里都选择“(None)”.

Pagination des données DataList et Repeater

图 6: 在UPDATE, INSERT, DELETE 标签的下拉里选择“(None)”

  因为GetProductsAsPagedDataSource方法需要两个参数,因此向导会提示我们选择参数源。page index和page size的值必须在postback过程中记下来。它们可以存在view state,querystring,session里或用其它技术来记录。本章我们使用querystring。

  分别使用querystring字段“pageIndex” 和“pageSize”来配置pageIndex和pageSize。见图7。由于用户第一次浏览页的时候没有querystring,因此还需要设置这两个参数的默认值。将pageIndex的默认值设为0(表示显示第一页数据),将pageSize的默认值设为4。

Pagination des données DataList et Repeater

图 7: 配置参数

  配置完ObjectDataSource后,Visual Studio自动为DataList创建一个ItemTemplate。修改它让它只显示product的name,category和supplier。将DataList的RepeatColumns属性设为2,Width设为“100%”, ItemStyle的Width设为 “50%”. 这样的设置会为两列提供相同的间距。完成这些后DataList和ObjectDataSource的标记语言看起来应该如下:

<asp:DataList ID="ProductsDefaultPaging" runat="server" Width="100%"
 DataKeyField="ProductID" DataSourceID="ProductsDefaultPagingDataSource"
 RepeatColumns="2" EnableViewState="False">
 <ItemTemplate>
  <h4><asp:Label ID="ProductNameLabel" runat="server"
   Text=&#39;<%# Eval("ProductName") %>&#39;></asp:Label></h4>
  Category:
  <asp:Label ID="CategoryNameLabel" runat="server"
   Text=&#39;<%# Eval("CategoryName") %>&#39;></asp:Label><br />
  Supplier:
  <asp:Label ID="SupplierNameLabel" runat="server"
   Text=&#39;<%# Eval("SupplierName") %>&#39;></asp:Label><br />
  <br />
  <br />
 </ItemTemplate>
 <ItemStyle Width="50%" />
</asp:DataList>
<asp:ObjectDataSource ID="ProductsDefaultPagingDataSource" runat="server"
 OldValuesParameterFormatString="original_{0}" TypeName="ProductsBLL"
 SelectMethod="GetProductsAsPagedDataSource">
 <SelectParameters>
  <asp:QueryStringParameter DefaultValue="0" Name="pageIndex"
    QueryStringField="pageIndex" Type="Int32" />
  <asp:QueryStringParameter DefaultValue="4" Name="pageSize"
    QueryStringField="pageSize" Type="Int32" />
 </SelectParameters>
</asp:ObjectDataSource>

注意:由于这里我们不实现任何更新或删除的功能,你可以禁用DataList的view state来减少页面的大小。

  第一次浏览页的时候,querystring里没有提供pageIndex 和pageSize的值,因此将使用默认的0和4。见图8。DataList将显示4条product记录。

Pagination des données DataList et Repeater

图 8: 显示4条Product

  由于还没有分页的界面,因此用户现在还不能直接导航到第二页。我们将在第四步里创建分页界面。现在我们只能直接在querystring里指定分页的参数来进行分页。例如,我们可以将地址从Paging.aspx改为Paging.aspx?pageIndex=2,然后回车,来浏览第二页。这样就可以看到第二页的数据了,见图9。

Pagination des données DataList et Repeater

图 9: 显示第二页数据

第四步: 创建分页界面

有很多不同的完成分页界面的方法。GridView, DetailsView, FormView 提供了4种不同的界面:

Next, Previous(后一页,前一页) – 用户可以浏览上一页或下一页.
Next, Previous, First(第一页), Last (最后一页)– 除了上面的功能,这个还包含第一页和最后一页。
Numeric (数字)–在分页界面上列出页数,用户可以随意的选择一个页 .
Numeric, First, Last – 在上一个功能的基础上增加了第一页和最后一页.

  对DataList 和Repeater而言,我们需要决定它的分页界面并实现它。这其中包含了需要创建web控件和当特定页的button被点时显示请求的页。另外某些分页界面的控件可能需要禁用。例如,当使用Next, Previous, First, Last这个模式来显示时,如果浏览第一页数据,那么第一页和前一页的button应该被禁用。

  本章我们使用 Next, Previous, First, Last界面。添加4个button,并将ID分别设为FirstPage,PrevPage,NextPage和LastPage。将Text设为“”, “Last >>”.

<asp:Button runat="server" ID="FirstPage" Text="<< First" />
<asp:Button runat="server" ID="PrevPage" Text="< Prev" />
<asp:Button runat="server" ID="NextPage" Text="Next >" />
<asp:Button runat="server" ID="LastPage" Text="Last >>" />

然后为每个button创建一个Click事件处理。呆会我们将添加代码来显示请求的页。

记下分页的总记录数

  不管选择哪种分页界面,我们都需要计算和记下分页的总记录数。总的行数(和page size)来决定总的页数,它决定了那些分页界面的控件需要增加或启用。在我们创建的Next, Previous, First, Last 界面里,page count(页数)在两种情况下需要被用到:

  判断我们是否在浏览最后一页,这种情况下Next 和Last buttons 需要禁用。
  如果用户点了Last button我们需要将它转到最后一页,它的索引等于page count减1。

  page count通过总行数除以page size(页数)来计算得到。例如我们要分页79条记录,每页显示4条,那么page count为20(79/4)。如果我们使用数字分页界面,就可以通过这个信息来决定要显示多少个数字页的button。如果分页界面只包含Next 和Last buttons,可以通过page count来什么时候禁用Next 和Last buttons。

  如果分页界面包含Last button(最后一页),我们需要在postback过程中记下分页的总记录数,这样在点Last button的时候我们可以获得最后一页的索引。为了方便实现这个,我们在ASP.NET页的后台代码里创建一个TotalRowCount属性来将这个值保存到view state里。

private int TotalRowCount
{
 get
 {
  object o = ViewState["TotalRowCount"];
  if (o == null)
   return -1;
  else
   return (int)o;
 }
 set
 {
  ViewState["TotalRowCount"] = value;
 }
}

  除了TotalRowCount外,还需要为page index,page size和page count创建页面级的只读属性来方便读取。

private int PageIndex
{
 get
 {
  if (!string.IsNullOrEmpty(Request.QueryString["pageIndex"]))
   return Convert.ToInt32(Request.QueryString["pageIndex"]);
  else
   return 0;
 }
}
private int PageSize
{
 get
 {
  if (!string.IsNullOrEmpty(Request.QueryString["pageSize"]))
   return Convert.ToInt32(Request.QueryString["pageSize"]);
  else
   return 4;
 }
}
private int PageCount
{
 get
 {
  if (TotalRowCount <= 0 || PageSize <= 0)
   return 1;
  else
   return ((TotalRowCount + PageSize) - 1) / PageSize;
 }
}

  

获取分页的总记录数

  从ObjectDataSource的Select()方法返回一个PagedDataSource对象包含所有的product记录,即使只有一部分会在DataList里显示。PagedDataSource的Count property 返回将在DataList里显示的项的数目。DataSourceCount property 返回PagedDataSource里的所有项的的总数目。因此我们需要将ASP.NET页的TotalRowCount属性赋值为PagedDataSource的DataSourceCount。

  我们为ObjectDataSource的Selectd事件创建一个event handler来完成这些。在Selectd的event handler里我们获取ObjectDataSource的Select()方法的返回值–在这种情况下是PagedDataSource。

protected void ProductsDefaultPagingDataSource_Selected
 (object sender, ObjectDataSourceStatusEventArgs e)
{
 // Reference the PagedDataSource bound to the DataList
 PagedDataSource pagedData = (PagedDataSource)e.ReturnValue;
 // Remember the total number of records being paged through
 // across postbacks
 TotalRowCount = pagedData.DataSourceCount;
}

显示请求的页的数据

  当用户点分页界面上的button时,我们需要显示请求的页的数据。由于分页的参数在querystring里指定,因此使用Response.Redirect(url)来让用户重新请求带合适分页参数的Paging.aspx页。例如,显示第二页的数据,我们将用户重定向到Paging.aspx?pageIndex=1。

  创建一个RedirectUser(sendUserToPageIndex)方法来重定向用户到Paging.aspx?pageIndex=sendUserToPageIndex。然后在四个按钮的Click事件处理里调用这个方法。在FirstPageClick里调用RedirectUser(0),在PrevPageClick里调用RedirectUser(PageIndex-1)。

protected void FirstPage_Click(object sender, EventArgs e)
{
 // Send the user to the first page
 RedirectUser(0);
}
protected void PrevPage_Click(object sender, EventArgs e)
{
 // Send the user to the previous page
 RedirectUser(PageIndex - 1);
}
protected void NextPage_Click(object sender, EventArgs e)
{
 // Send the user to the next page
 RedirectUser(PageIndex + 1);
}
protected void LastPage_Click(object sender, EventArgs e)
{
 // Send the user to the last page
 RedirectUser(PageCount - 1);
}
private void RedirectUser(int sendUserToPageIndex)
{
 // Send the user to the requested page
 Response.Redirect(string.Format("Paging.aspx?pageIndex={0}&pageSize={1}",
  sendUserToPageIndex, PageSize));
}

  完成Click事件处理后,DataList的记录现在可以通过button来分页了,你可以测试一下。

禁用分页控件

  现在无论浏览哪页四个按钮都是可用的。然而我们在浏览第一页时需要禁用 First 和Previous buttons ,在浏览最后一页时需要禁用Next 和Last buttons。通过ObjectDataSource的Select()方法返回的PagedDataSource对象有几个属性– IsFirstPage 和 IsLastPage –通过它们可以判断用户浏览的是否是第一或最后一页数据。添加下面的代码到ObjectDataSource的Selected事件处理里:

// Configure the paging interface based on the data in the PagedDataSource
FirstPage.Enabled = !pagedData.IsFirstPage;
PrevPage.Enabled = !pagedData.IsFirstPage;
NextPage.Enabled = !pagedData.IsLastPage;
LastPage.Enabled = !pagedData.IsLastPage;

  添加完后,当浏览第一页时,First 和Previous buttons 将被禁用。当浏览最后一页时,Next 和  Last buttons 将被禁用。

  我们最后来实现在分页界面里通知用户他们当前是浏览的哪页和一共有多少页。添加一个Label控件并将ID设为CurrentPageNumber。在ObjectDataSource的Selected事件处理中设置它的Text属性,让它显示当前浏览的页(PageIndex+1)和总页数(PageCount)。

// Display the current page being viewed...
CurrentPageNumber.Text = string.Format("You are viewing page {0} of {1}...",
 PageIndex + 1, PageCount);

  图10是第一次浏览Paging.aspx页的样子。由于querystring是空的,因此DataList默认显示最开始的4条product。First 和Previous buttons 被禁用。点Next 会显示下面的4条记录(见图11),而First 和Previous buttons 同时被启用了。

图 10: 第一页数据

Pagination des données DataList et Repeater

图 11: 第二页数据

  注意:分页界面可以进一步改善,比如增加允许用户来指定每页显示多少记录。例如添加一个DropDownList列出page size的选项,比如5, 10, 25, 50, 和ALL。用户选择了page size后会重定向到Paging.aspx?pageIndex=0&pageSize=selectedPageSize。我将这个作为练习留给读者自己完成。

使用自定义分页

  DataList使用没有效率的默认分页技术。当大数据量时,我们需要使用自定义分页。虽然实现的细节有所不同,但是分页里的概念和默认分页是一样的。默认分页时,使用ProductsBLL类的GetProductsPaged方法(而不是GetProductsAsPagedDataSource)。正如在大数据量时提高分页的效率 里讨论的那样,GetProductsPaged需要传入开始行的索引和行的最大数目。这些参数可以通过默认分页里使用的querystring里的pageIndex和pageSize参数来保存。

  由于自定义分页里没有PagedDataSource,所以需要其它技术来决定总记录数和判断我们是否显示第一或最后一页数据。ProductsBLL类的TotalNumberOfProducts()方法返回roduct的总记录数。而为了判断是否浏览的是第一页数据,我们需要检查开始行的索引–如果是0,则表示在浏览第一页。如果开始行的索引加上最大的行数大于或等于总记录数则表示在最后一页.我们将在下章详细的讨论如何实现自定义分页。

总结

  DataList和Repeater都没有提供象GridView, DetailsView, FormView 那样的分页的支持,这样的功能需要我们来实现。最简单的实现方法是使用默认分页,将所有的product都包装到PagedDataSource里,然后绑定PagedDataSource到DataList或Repeater。本章我们在ProductsBLL类里添加GetProductsAsPagedDataSource方法,它返回PagedDataSource。ProductsBLL类已经包含了自定义分页需要的方法– GetProductsPaged和TotalNumberOfProducts。

  不管是自定义方法里获取精确的记录还是默认方法里获取所有记录,我们都需要手动添加分页界面。本章我们创建的是包含4个button控件的Next, Previous, First, Last interface 。当然还添加了一个显示当前页和总页数的Label控件。

更多Pagination des données DataList et Repeater相关文章请关注PHP中文网!


Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn