ASP.NET Tip: Creating Paging for a Repeater Control

A common question is "How do I implement paging within a Repeater?" Although the beauty of the Repeater control is its flexibility, you're on your own for building most functions. ASP.NET 2.0 has included some new controls that provide paging, as does the DataGrid in ASP.NET 1.1. However, this tip shows you how to roll your own paging for a simple data viewer.

Here's the code behind for the page this tip builds:

using System;
using System.Data;
using System.Collections;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Data.SqlClient;

public partial class PagedRepeater : System.Web.UI.Page
{
   public int PageNumber
   {
      get
      {
         if (ViewState["PageNumber"] != null)
            return Convert.ToInt32(ViewState["PageNumber"]);
         else
            return 0;
      }
      set
      {
         ViewState["PageNumber"] = value;
      }
   }

   protected override void OnInit(EventArgs e)
   {
      base.OnInit(e);
      rptPages.ItemCommand +=
         new RepeaterCommandEventHandler(rptPages_ItemCommand);
   }

   protected void Page_Load(object sender, EventArgs e)
   {
      if (!Page.IsPostBack)
      LoadData();
   }

   private void LoadData()
   {
      SqlConnection cn = new SqlConnection("your connection goes
                                            here");
      cn.Open();
      SqlDataAdapter da = new SqlDataAdapter("your query goes
                                              here", cn);
      DataTable dt = new DataTable();
      da.Fill(dt);
      cn.Close();

      PagedDataSource pgitems = new PagedDataSource();
      DataView dv = new DataView(dt);
      pgitems.DataSource = dv;

      pgitems.AllowPaging = true;
      pgitems.PageSize = 25;
      pgitems.CurrentPageIndex = PageNumber;

      if (pgitems.PageCount > 1)
      {
         rptPages.Visible = true;
         ArrayList pages = new ArrayList();
         for (int i = 0; i < pgitems.PageCount; i++)
         pages.Add((i + 1).ToString());
         rptPages.DataSource = pages;
         rptPages.DataBind();

      }
      else
         rptPages.Visible = false;

      rptItems.DataSource = pgitems;
      rptItems.DataBind();
   }

   void rptPages_ItemCommand(object source,
                             RepeaterCommandEventArgs e)
   {
      PageNumber = Convert.ToInt32(e.CommandArgument) - 1;
      LoadData();
   }


}

This is the ASPX web page:

<%@ Page Language="C#"
         AutoEventWireup="true"
         CodeFile="pagedrepeater.aspx.cs"
         Inherits="PagedRepeater" %>
<html>
<head><title>Paged Repeater</title>
</head>
<body>
<form runat="server">
      <asp:Repeater ID="rptPages" Runat="server">
      <HeaderTemplate>
      <table cellpadding="0" cellspacing="0" border="0">
      <tr class="text">
         <td><b>Page:</b>&nbsp;</td>
         <td>
      </HeaderTemplate>
      <ItemTemplate>
         <asp:LinkButton ID="btnPage"
                         CommandName="Page"
                         CommandArgument="<%#
                         Container.DataItem %>"
                         CssClass="text"
                         Runat="server"><%# Container.DataItem %>
                         </asp:LinkButton>&nbsp;
      </ItemTemplate>
      <FooterTemplate>
         </td>
      </tr>
      </table>
      </FooterTemplate>
      </asp:Repeater>

      <asp:Repeater ID="rptItems" runat="server">
      <HeaderTemplate>
      <ul>
      </HeaderTemplate>
      <ItemTemplate>
      <li><%# Eval("pkItemID") %>: <%# Eval("Description") %></li>
      </ItemTemplate>
      <FooterTemplate>
      </ul>
      </FooterTemplate>

      </asp:Repeater>
</form>
</body>
</html>

The page uses one Repeater for the page numbers and a second one for the items. This example shows items from a product catalog, but any database table will do. To start, create a ViewState property (see the previous tip) to store the current page number. This property also is coded to return a zero, which is the first page number (at least as far as the database is concerned).

When the page is first loaded, the code calls the LoadData routine, which gets a DataTable containing the records. Then, that is connected to the PagedDataSource class by way of a DataView object. The DataView also can provide sorting; this makes it easy to allow users to sort by a particular column heading. You simply create another ViewState property and store the sort field at this point.

The example has a page size of 25, which is put into the PagedDataSource object. Based on the number of rows, the PageCount property is populated with the total number of "pages" in the data source. The code forces the CurrentPageIndex to the default page number of zero, which positions it at the first record on page 0. The other bonus to the PagedDataSource object is that it will give back only 25 records, which means you don't have to keep count or manually bind it to the item list repeater. This is a nice change from the code you may have done in ASP to perform this same function.

Next, the example needs to build the page number list; the code does this with an ArrayList holding each page number as a string. Note that the example adjusts the page number up by one because the average person doesn't understand that page zero is the first page—the user will see page 1 as the first page.

The example wires up an event handler to respond to the clicks in the paging repeater next. It converts the CommandArgument and subtracts one from it because it's showing the value in the repeater as one more than the actual page number. Calling LoadData repositions the list to the appropriate page.

The result is a list of pages above a short item list that changes as the user selects different pages. This model can be expanded, as previously mentioned, to support a user-selectable page length or sorting options. However, if you change the page size, be aware that the number of pages will change and the previous page number may be invalid. The PagedDataSource won't generate an error if you pick a CurrentPageIndex outside the valid range, but you should be sure to trap for this condition anyway.

About the Author

Eric Smith is the owner of Northstar Computer Systems, a web-hosting company based in Indianapolis, Indiana. He is also a MCT and MCSD who has been developing with .NET since 2001. In addition, he has written or contributed to 12 books covering .NET, ASP, and Visual Basic. Send him your questions and feedback via e-mail at questions@techniquescentral.com.



Comments

  • Nice article

    Posted by maislam on 06/28/2013 03:03am

    Nice article.I want CSS.Please attached css file. Thanks for sharing code.

    Reply
  • Thanks for Your article

    Posted by Nazmus Shahadat on 04/14/2013 11:46pm

    I am a bangladeshi web developer. I follow your code. I overcome with your code. Many many thanks. May god bless you.

    Reply
  • Thanks for Your article

    Posted by Nazmus Shahadat on 04/14/2013 11:44pm

    I am a web bangladeshi web Developer. I am working asp.net and php both. I am very very glad to you. I am follow your code and also executed various problem. I overcome with your code. Most thanks.

    Reply
  • Great article

    Posted by Dogan Cakmak on 08/10/2012 03:43am

    This article is one of the best articles I have ever read.

    Reply
  • srry buddy i can't find my answer

    Posted by ravitiwari on 06/19/2007 09:46pm

    i want to implement the paging on the simple link which i have provided for the books on a single page... plz give me the answer...

    Reply
Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Protecting business operations means shifting the priorities around availability from disaster recovery to business continuity. Enterprises are shifting their focus from recovery from a disaster to preventing the disaster in the first place. With this change in mindset, disaster recovery is no longer the first line of defense; the organizations with a smarter business continuity practice are less impacted when disasters strike. This SmartSelect will provide insight to help guide your enterprise toward better …

  • Where the business performance of their mobile app portfolios are concerned, most companies are flying blind. While traditional application portfolios are held to all kinds of ROI measure, the investment plan for mobile apps -- increasingly the more crucial bet -- is made by guesswork and dart-throwing. This interactive e-book investigates how mobile is driving the need for app and portfolio measures unlike any we saw in the days of web. Good mobile analytics must deliver leading indicators of user experience …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds