Click here to Skip to main content
15,895,709 members
Articles / Web Development / ASP.NET

A Basic ASP.NET Pager Control

Rate me:
Please Sign up or sign in to vote.
4.36/5 (11 votes)
21 Oct 2008LGPL33 min read 67.8K   1.5K   32  
A basic ASP.NET Pager User Control
//-----------------------------------------------------------------------
// <copyright file="Pager.ascx.cs" company="Thap Ltd">
//     Copyright (c) Thap Ltd. All rights reserved.
// </copyright>
// <author>Tony Williams</author>
//-----------------------------------------------------------------------
namespace ThapWebControls
{
    using System;
    using System.Collections.Generic;
    using System.Web.UI;
    using System.Web.UI.WebControls;

    /// <summary>Event agruments for pager control</summary>
    public class PagerEventArgs : EventArgs
    {
        /// <summary>Gets or sets the page number that is fired</summary>
        public int Number
        {
            get; set;
        }

        /// <summary>Gets or sets a value indicating whether the first button has been click</summary>
        public bool First
        {
            get; set;
        }

        /// <summary>Gets or sets a value indicating whether the previous button has been click</summary>
        public bool Previous
        {
            get; set;
        }

        /// <summary>Gets or sets a value indicating whether the next button has been click</summary>
        public bool Next
        {
            get; set;
        }

        /// <summary>Gets or sets a value indicating whether the last button has been click</summary>
        public bool Last
        {
            get; set;
        }

        /// <summary>Gets or sets the number of rows each page contains</summary>
        public int PageSize
        {
            get;
            set;
        }
    }

    /// <summary>Provides a basic paging control that fires an event when a link is clicked</summary>
    public partial class Pager : UserControl
    {
        #region Events
        /// <summary>Fires when a  link is clicked, the text with in the object (link button) is the number</summary>
        public event EventHandler<PagerEventArgs> Change;
        #endregion

        #region Properties
        /// <summary>
        /// Gets or sets total number of pages the datasource is capable of.
        /// </summary>
        public int TotalPages
        {
            get
            {
                if (ViewState["TotalPages"] == null)
                {
                    ViewState["TotalPages"] = 0;
                }

                return Convert.ToInt32(ViewState["TotalPages"]);
            }

            set
            {
                ViewState["TotalPages"] = value;
            }
        }

        /// <summary>
        /// Gets or sets the "First" record display text
        /// </summary>
        public string FirstText
        {
            get; set;
        }

        /// <summary>
        /// Gets or sets the "Previous" record display text
        /// </summary>
        public string PreviousText
        {
            get; set;
        }

        /// <summary>
        /// Gets or sets the "Next" record display text
        /// </summary>
        public string NextText
        {
            get; set;
        }

        /// <summary>
        /// Gets or sets the "Last" record display text
        /// </summary>
        public string LastText
        {
            get; set;
        }

        /// <summary>
        /// Gets or sets the seperator display text
        /// </summary>
        public string Separator
        {
            get;
            set;
        }

        /// <summary>
        /// Enables/disables the "GoTo" functionality
        /// </summary>
        public bool ShowGoTo
        {
            get;
            set;
        }

        /// <summary>
        /// Gets or sets the number of pages to display at
        /// </summary>
        public int NumberOfPages
        {
            get
            {
                if (ViewState["NumberOfPages"] == null)
                {
                    ViewState["NumberOfPages"] = 10;
                }

                return Convert.ToInt32(ViewState["NumberOfPages"]);
            }

            set
            {
                ViewState["NumberOfPages"] = value;
            }
        }

        /// <summary>
        /// Gets or sets the current page number
        /// </summary>
        public int CurrentPageNumber
        {
            get
            {
                if (ViewState["CurrentPageNumber"] == null)
                {
                    ViewState["CurrentPageNumber"] = 1;
                }

                return Convert.ToInt32(ViewState["CurrentPageNumber"]);
            }

            set
            {
                ViewState["CurrentPageNumber"] = value;
            }
        }

        /// <summary>
        /// Gets or sets the page size, mainley used as a helpful reminder
        /// </summary>
        public int PageSize
        {
            get
            {
                if (ViewState["PageSize"] == null)
                {
                    ViewState["PageSize"] = 10;
                }

                return Convert.ToInt32(ViewState["PageSize"]);
            }

            set
            {
                ViewState["PageSize"] = value;
            }
        }

        /// <summary>
        /// Gets or sets the css class for the currently selected tab
        /// </summary>
        public string CssClass
        {
            get; set;
        }

        #endregion 

        #region Public Methods
        /// <summary> Generates the pagers links based upon the controls properties </summary>
        public void GenerateLinks()
        {
            var display = new List<int>();
            int minimum;
            int maximum;
            CalculateBoundry(this.NumberOfPages, this.TotalPages, this.CurrentPageNumber, out minimum, out maximum);
            for (int i = minimum; i <= maximum; i++)
            {
                display.Add(i);
            }

            RepeaterNumbers.DataSource = display;
            RepeaterNumbers.DataBind();

            bool dataToDisplay = this.TotalPages > 0;

            LinkButtonFirst.Visible = dataToDisplay;
            LinkButtonPrevious.Visible = dataToDisplay;
            LinkButtonNext.Visible = dataToDisplay;
            LinkButtonLast.Visible = dataToDisplay;

            if (this.TotalPages < 1 || !this.ShowGoTo)
            {
                this.ButtonGoTo.Visible = false;
                this.TextBoxGoTo.Visible = false;
            }
            else
            {
                this.ButtonGoTo.Visible = true;
                this.TextBoxGoTo.Visible = true;
            }

            this.LinkButtonFirst.Enabled = !(this.CurrentPageNumber <= 1);
            this.LinkButtonPrevious.Enabled = !(this.CurrentPageNumber <= 1);
            this.LinkButtonNext.Enabled = !(this.CurrentPageNumber >= this.TotalPages);
            this.LinkButtonLast.Enabled = !(this.CurrentPageNumber >= this.TotalPages);
        }
        #endregion

        #region Protected Methods
        /// <summary>
        /// Runs the initlaisation code
        /// </summary>
        /// <param name="sender">The object that fired this event</param>
        /// <param name="e">Additional arguments passes</param>
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!Page.IsPostBack)
            {
                this.LinkButtonFirst.Text = this.FirstText ?? "|<";
                this.LinkButtonPrevious.Text = this.PreviousText ?? "<";
                this.LinkButtonNext.Text = this.NextText ?? ">";
                this.LinkButtonLast.Text = this.LastText ?? ">|";
            }
        }

        /// <summary>
        /// Determins if the current page number is the same as the page number passed through
        /// </summary>
        /// <param name="pageNumber">Page number to check against</param>
        /// <returns>True if they match</returns>
        protected bool IsCurrentPage(int pageNumber)
        {
            return pageNumber == this.CurrentPageNumber;
        }

        #region buttons clicked
        /// <summary>Fires the FirstClicked event</summary>
        /// <param name="sender">Object that fires this event</param>
        /// <param name="e">Additional arguments passed</param>
        protected void LinkButtonFirst_Click(object sender, EventArgs e)
        {
            if (this.Change != null)
            {
                this.CurrentPageNumber = 1;
                var args = new PagerEventArgs
                               {
                                   First = true, 
                                   Previous = false, 
                                   Next = false, 
                                   Last = false, 
                                   Number = this.CurrentPageNumber, 
                                   PageSize = this.PageSize
                               };
                this.Change(this, args);
            }
        }

        /// <summary>Fires the PreviousClicked event</summary>
        /// <param name="sender">Object that fires this event</param>
        /// <param name="e">Additional arguments passed</param>
        protected void LinkButtonPrevious_Click(object sender, EventArgs e)
        {
            if (this.Change != null)
            {
                this.CurrentPageNumber--;
                var args = new PagerEventArgs
                               {
                                   First = false, 
                                   Previous = true, 
                                   Next = false, 
                                   Last = false, 
                                   Number = this.CurrentPageNumber, 
                                   PageSize = this.PageSize
                               };
                this.Change(this, args);
            }
        }

        /// <summary>Fires the NumbereClicked event</summary>
        /// <param name="sender">Object that fires this event</param>
        /// <param name="e">Additional arguments passed</param>
        protected void LinkButtonNumber_Click(object sender, EventArgs e)
        {
            if (this.Change != null)
            {
                var number = Convert.ToInt32(((LinkButton)sender).Text);
                this.CurrentPageNumber = number;
                var args = new PagerEventArgs
                               {
                                   First = false,
                                   Previous = false,
                                   Next = false,
                                   Last = false,
                                   Number = number,
                                   PageSize = this.PageSize
                               };
                this.Change(this, args);
            }
        }

        /// <summary>Fires the NextClicked event</summary>
        /// <param name="sender">Object that fires this event</param>
        /// <param name="e">Additional arguments passed</param>
        protected void LinkButtonNext_Click(object sender, EventArgs e)
        {
            if (this.Change != null)
            {
                this.CurrentPageNumber++;
                var args = new PagerEventArgs
                               {
                                   First = false,
                                   Previous = false,
                                   Next = true,
                                   Last = false,
                                   Number = this.CurrentPageNumber,
                                   PageSize = this.PageSize
                               };
                this.Change(this, args);
            }
        }

        /// <summary>Fires the LastClicked event</summary>
        /// <param name="sender">Object that fires this event</param>
        /// <param name="e">Additional arguments passed</param>
        protected void LinkButtonLast_Click(object sender, EventArgs e)
        {
            if (this.Change != null)
            {
                this.CurrentPageNumber = this.TotalPages;
                var args = new PagerEventArgs
                               {
                                   First = false,
                                   Previous = false,
                                   Next = false,
                                   Last = true,
                                   Number = this.CurrentPageNumber,
                                   PageSize = this.PageSize
                               };
                this.Change(this, args);
            }
        }

        /// <summary>Fires the NumbereClicked event</summary>
        /// <param name="sender">Object that fires this event</param>
        /// <param name="e">Additional arguments passed</param>
        protected void ButtonGoTo_Click(object sender, EventArgs e)
        {
            if (this.Change != null)
            {
                int number;
                if (int.TryParse(this.TextBoxGoTo.Text, out number))
                {
                    if (number <= this.TotalPages)
                    {
                        this.CurrentPageNumber = number;
                        var args = new PagerEventArgs
                                       {
                                           First = false,
                                           Previous = false,
                                           Next = false,
                                           Last = false,
                                           Number = number,
                                           PageSize = this.PageSize
                                       };
                        this.Change(this, args);
                    }
                }
            }
        }
        #endregion

        #endregion

        #region Private Methods
        /// <summary>
        /// Calculates the upper/lower boundries for the pager to use when generating the page tabs
        /// </summary>
        /// <param name="maximumPages">Maximum nuber of pages along the bottom of the pager</param>
        /// <param name="totalPages">Total number of pages in the datasource</param>
        /// <param name="currentPage">Current page number</param>
        /// <param name="lowerBound">Returns the lowest boundry</param>
        /// <param name="upperBound">Returns the upper boundry</param>
        private static void CalculateBoundry(int maximumPages, int totalPages, int currentPage, out int lowerBound, out int upperBound)
        {
            if (totalPages < maximumPages)
            {
                lowerBound = 1;
                upperBound = totalPages;
            }
            else
            {
                // NOTE: Look in to saturated arithmetic
                var rightDisplay = maximumPages / 2;
                var leftDisplay = maximumPages - rightDisplay;

                lowerBound = currentPage - leftDisplay;
                var lowerOffset = 0 - lowerBound;

                upperBound = currentPage + rightDisplay + (lowerOffset > 0 ? lowerOffset : 0);
                var upperOffset = upperBound > totalPages ? upperBound - totalPages : 0;
                upperBound = (totalPages - upperBound) > 0 ? upperBound : totalPages;

                lowerBound = lowerBound > 0 ? (lowerBound + lowerBound > upperOffset ? lowerBound - upperOffset + 1 : 1) : 1;
            }
        }

        #endregion
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The GNU Lesser General Public License (LGPLv3)


Written By
Software Developer (Senior) Thap
United Kingdom United Kingdom
Software Developer for Thap in Middlesbrough, UK.
Former Ice-cream man too.

Comments and Discussions