Create a Google Style paging component in C#

Several years ago I wrote a an article about Creating a Google Style paging component in XSLT. Some users pointed out to me that the paging component wasn’t exactly Google style. Especially using the arrows didn’t comply with how Google does it, but apart from that it mimicked the Google paging very well.

This is another implementation, this time in C#. Again, I’m not using the Google style exactly. Instead I’m using a “rolling numbers” principle. The component specifies how many numbers should (at most) be present at a time, as demonstated here:

3 types of paging

3 states in the paging component

(Google uses a simple method where it defines how many number should be present before and after the current page (like my first XSLT), but this paging is better at sticking to the middle of a web page).

In this example (and in the code) I specify that I want 10 pages to be present.

Here is the code. First I define a Page class containing the information about a page. This is very simple, but you can build it as advanced as you need it.

/// <summary>
/// Page class containing the information used to create a paging control
/// </summary>
public class Page
{
  /// <summary>
  /// Gets or sets the title.
  /// </summary>
  /// <value>The title.</value>
  public string Title { get; set; }
   
  /// <summary>
  /// Gets or sets the page number.
  /// </summary>
  /// <value>The page num.</value>
  public string PageNum { get; set; }

  /// <summary>
  /// Gets or sets a value indicating whether this page is the current page.
  /// </summary>
  /// <value><c>true</c> if [current page]; otherwise, <c>false</c>.</value>
  public bool CurrentPage { get; set; }
}

Then I have a simple class returning a IEnumerable list of Page classes:

using System.Collections.Generic;

namespace MyProject
{
  /// <summary>
  /// Class generating a enumerable list of pages
  /// </summary>
  /// <remarks>
  /// Primarily used by the thumbnail list to create a paging control
  /// </remarks>
  public class PagingProvider
  {
    /// <summary>
    /// Creates a list of page numbers to be enumerated in a paging control.
    /// </summary>
    /// <remarks>
    /// Paging is 1-based, meaning that the first page is called page 1.
    /// </remarks>
    /// <param name="pageSize">Size of the page.</param>
    /// <param name="totalItems">The total items.</param>
    /// <param name="currentPage">The current page.</param>
    /// <returns></returns>
    public IEnumerable<Page> CreatePages(int pageSize, int totalItems, int currentPage)
    {
      List<Page> pages = new List<Page>();
      int totalPages = (totalItems / pageSize) + 1;
      int startIndex = 0;
      int endIndex = totalPages;
     
      if (totalPages > 10)
      {
        startIndex = currentPage - 5;
        endIndex = currentPage + 5;
        if (startIndex < 0)
        {
          startIndex = 0;
          endIndex = startIndex + 10;
        }
        if (endIndex > totalPages)
        {
          endIndex = totalPages;
          startIndex = totalPages - 10;
        }
      }
      pages.Add(new Page { Title = "««", PageNum = "1", CurrentPage = false });
      if (currentPage == 1)
        pages.Add(new Page { Title = "«", PageNum = (currentPage).ToString(), CurrentPage = false });
      else
        pages.Add(new Page { Title = "«", PageNum = (currentPage - 1).ToString(), CurrentPage = false });
      for (int i=startIndex;i<endIndex;i++)
      {
        Page page = new Page {Title = (i + 1).ToString(), PageNum = (i + 1).ToString(), CurrentPage = i == (currentPage-1)};
        pages.Add(page);
      }
      if (currentPage == totalPages)
        pages.Add(new Page { Title = "»", PageNum = (currentPage).ToString(), CurrentPage = false });
      else
        pages.Add(new Page { Title = "»", PageNum = (currentPage + 1).ToString(), CurrentPage = false });
      pages.Add(new Page { Title = "»»", PageNum = totalPages.ToString(), CurrentPage = false });
      return pages;
    }
  }
}

The function, CreatePages, is called using the information about the data to page, the page size (how many items you have per page), total number of items and the current page. The paging can be hooked to an asp:Repeater for example:

<asp:Repeater ID="repPagesBottom" runat="server" onitemcommand="repPages_ItemCommand">
  <HeaderTemplate>
    <div>
  </HeaderTemplate>
  <ItemTemplate>
    <span>
      <asp:Button CommandName="changePage" CommandArgument='<%# Eval("PageNum") %>' Text='<%# Eval("Title") %>' runat="server" CssClass='<%# Eval("CurrentPage") %>' />
    </span>
   </ItemTemplate>
   <FooterTemplate>
     </div>
   </FooterTemplate>
</asp:Repeater>

Simply apply the output from the CreatePages to the Datasource of the repeater.

About briancaos

Developer at Pentia A/S since 2003. Have developed Web Applications using Sitecore Since Sitecore 4.1.
This entry was posted in .net, c#, General .NET and tagged , , , . Bookmark the permalink.

3 Responses to Create a Google Style paging component in C#

  1. Andreas says:

    thanks bro

  2. Ian says:

    I’m not seeing how to hook this into the DataSource. Is there something in the code-behind where it’s output is applied to the datasource? Thanks!

  3. briancaos says:

    Whereever you need to update the paging control, you do thr manual databind. It’s very common that you do this in the Page_Load or Page_Init.
    This is not the solution, just an example on how it may look. I’ll pretend I’m using the paging to page between a search result. The search engine have returned a number of search results for me, and the search engibe have also a property that explains how many results in total there are.

    This is what I would do on the Page_Load:

    PagingProvider provider = new PagingProvider();
    int pageSize = 10;
    int totalItems = GetTotalCountFromSearch()
    int currentPage = 0;
    repPagesBottom.DataSource = provider.CreatePages(pageSize, totalItems, currentPage);
    repPagesBottom.DataBind();

    In my example I use a commandbutton, which gives an event when I click one of the numbers. I can use this to do the paging:

    protected void repPagesBottom_ItemCommand(object source, RepeaterCommandEventArgs e)
    {
    if (e.CommandName == "changePage")
    {
    // Remember to update the search result as well
    PagingProvider provider = new PagingProvider();
    int pageSize = 10;
    int totalItems = GetTotalCountFromSearch()
    int currentPage = int.Parse((string) e.CommandArgument);
    repPagesBottom.DataSource = provider.CreatePages(pageSize, totalItems, currentPage);
    repPagesBottom.DataBind();
    }
    }

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s