The Paginated repeater is an extension of the standard repeater to add in pagination capabilities.  It is does it by wrapping the datasource with the PagedDataSource, which is a data source wrapper available in asp.net.   I added in a NumberOfPagesToShow attribute, which determines how many of the numbers to show at the top of control to move through the pages before showing a ....  The TableWidth attribute, which is used to put into the table which creates the pagination details at the top of the control.  PageSize and PageIndex are both pretty much straightforward in what they do.

The PaginatedRepeater works by overloading the OnLoad function to find the datasource at that point in time and pass it on down to the main Repeater object.  It also determines if the request is a post back and sets the page index to the correct value.  The DataBind() call at the bottom of this function connects up and completes the data binding of the object, this is what connects the repeater to the actual data for rending.

The OnPreRender function is used to register a field which keeps track of the next page, this allows the javascript code to correctly move onto the next page when the next and previous buttons are clicked on the page.  The OnPreRender function also registers the javascript to be used in the control.

The Render function does all the work, it wraps a table around the actual control which puts in the numbers, the current page number and works out which numbers to actually show.  It switches on the PagerButtons enumerate type, that is used in other pager objects, to determine what type of pagination buttons to use and show.  The NavigateUrl on the controls are setup with javascript to do the pagination.  The code to this class is included below.

 

using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Collections;

namespace CustomControls
{

    /// <summary>
    /// Summary description for PaginatedRepeater
    /// </summary>
    public class PaginatedRepeater : Repeater
    {
        private PagedDataSource _pagedDataSource = new PagedDataSource();
        private PagerButtons _pagerbuttons = PagerButtons.NumericFirstLast;
        private Unit _tableWidth = new Unit("100%");
        private int _numToShow = 10;
        private string _dataSourceId = "";

        public PaginatedRepeater()
        {
            _pagedDataSource.AllowPaging = true;
            DataSource = _pagedDataSource;
        }

        public override string DataSourceID
        {
            get
            {
                return _dataSourceId;
            }
            set
            {
                if (value == null)
                {
                    _dataSourceId = "";
                }
                else
                {
                    _dataSourceId = value;
                }
            }
        }

        /// <summary>
        /// The number of pages to show when putting up a pagination thingy.
        /// </summary>
        public int NumberOfPagesToShow
        {
            get { return _numToShow; }
            set { _numToShow = value; }
        }

        /// <summary>
        /// The width of the table.
        /// </summary>
        public Unit TableWidth
        {
            get { return _tableWidth; }
            set { _tableWidth = value; }
        }

        /// <summary>
        /// Which buttons to show where.
        /// </summary>
        public PagerButtons PagerButtons
        {
            get { return _pagerbuttons; }
            set { _pagerbuttons = value; }
        }

        /// <summary>
        /// The current page index.
        /// </summary>
        public int PageIndex
        {
            get
            {
                return _pagedDataSource.CurrentPageIndex;
            }
            set
            {
                _pagedDataSource.CurrentPageIndex = value;
            }
        }

        /// <summary>
        /// The current page size.
        /// </summary>
        public int PageSize
        {
            get
            {
                return _pagedDataSource.PageSize;
            }
            set
            {
                _pagedDataSource.PageSize = value;
            }
        }

        protected override void OnLoad(EventArgs e)
        {
            if (DataSourceID != "")
            {
                object frog = this.Page.FindControl(DataSourceID);
                DataSourceID = "";
                if (frog is ObjectDataSource)
                {
                    ObjectDataSource data = (ObjectDataSource)frog;

                    _pagedDataSource.DataSource = data.Select();
                }
            }
            if (Page.IsPostBack)
            {
                string str = Page.Request.Form["__NEXTPAGE"];
                int pos = 0;
                try
                {
                    pos = Int32.Parse(str);
                }
                catch (FormatException)
                {
                }

                _pagedDataSource.CurrentPageIndex = pos;
            }
            DataBind();
            base.OnLoad(e);
        }

        protected override void OnPreRender(EventArgs args)
        {
            _pagedDataSource.DataSource = _pagedDataSource.DataSource;
            if (Page != null)
            {
                //Add hidden fields used to store the next page the user wants to visit
                //Note that the __NEXTPAGE value could be a previous page or a next page
                Page.ClientScript.RegisterHiddenField("__NEXTPAGE", "");

                //Add javascript used for pagination
                if (!Page.ClientScript.IsClientScriptBlockRegistered("Paginate"))
                {
                    Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "Paginate",
                         "<script language=\"javascript\">\r\n" +
                         "<!--\r\n" +
                         " function __doPaginate (page) {\r\n" +
                         "    // Javascript pagination logic\r\n" +
                        "        var element = document.forms[0]['__NEXTPAGE'];\r\n" +
                        "        if (element) {\r\n" +
                        "            element.value = page;\r\n" +
                        "            __doPostBack('" + this.ID + "', '');\r\n" +
                        "        }\r\n" +
                         " }\r\n" +
                         "// -->\r\n" +
                         "</script>\r\n");
                }
            }

            base.OnPreRender(args);
        }

        protected override void Render(HtmlTextWriter writer)
        {
            Table table;
            TableRow row;
            TableCell cell;
            HyperLink link;
            Literal lit;
            
            table = new Table();
            table.Width = _tableWidth;
            table.CellPadding = 0;
            table.CellSpacing = 0;
            table.BorderWidth = 0;

            // Single row with all the stuff in it.
            row = new TableRow();
            row.CssClass = "Pager";
            table.Rows.Add(row);

            switch (_pagerbuttons)
            {
                case PagerButtons.NextPreviousFirstLast:
                case PagerButtons.NextPrevious:
                    if (_pagedDataSource.PageCount > 1)
                    {
                        if (_pagedDataSource.CurrentPageIndex > 1 && _pagerbuttons == PagerButtons.NextPreviousFirstLast)
                        {
                            // First.
                            cell = new TableCell();
                            link = new HyperLink();
                            cell.HorizontalAlign = HorizontalAlign.Right;
                            link.Text = "<<";
                            link.NavigateUrl = "javascript: __doPaginate(0);";
                            cell.Controls.Add(link);
                            row.Cells.Add(cell);
                        }
                        if (_pagedDataSource.CurrentPageIndex > 0)
                        {
                            // Now we have a previous.
                            cell = new TableCell();
                            link = new HyperLink();
                            cell.HorizontalAlign = HorizontalAlign.Right;
                            link.Text = "<";
                            link.NavigateUrl = "javascript: __doPaginate(" + (_pagedDataSource.CurrentPageIndex - 1) + ");";
                            cell.Controls.Add(link);
                            row.Cells.Add(cell);
                        }
                        if (_pagedDataSource.CurrentPageIndex < _pagedDataSource.PageCount - 1)
                        {
                            // Next
                            cell = new TableCell();
                            link = new HyperLink();
                            cell.HorizontalAlign = HorizontalAlign.Right;
                            link.Text = ">";
                            link.NavigateUrl = "javascript: __doPaginate(" + (_pagedDataSource.CurrentPageIndex + 1) + ");";
                            cell.Controls.Add(link);
                            row.Cells.Add(cell);
                        }
                        if (_pagedDataSource.CurrentPageIndex < _pagedDataSource.PageCount - 2 && _pagerbuttons == PagerButtons.NextPreviousFirstLast)
                        {
                            // First.
                            cell = new TableCell();
                            link = new HyperLink();
                            cell.HorizontalAlign = HorizontalAlign.Right;
                            link.Text = ">>";
                            link.NavigateUrl = "javascript: __doPaginate(" + (_pagedDataSource.PageCount - 1) + ");";
                            cell.Controls.Add(link);
                            row.Cells.Add(cell);
                        }
                    }
                    break;
                case PagerButtons.Numeric:
                case PagerButtons.NumericFirstLast:
                    if (_pagedDataSource.PageCount > 1)
                    {
                        int start = _pagedDataSource.CurrentPageIndex - (_numToShow / 2);
                        if (start < 0)
                        {
                            start = 0;
                        }
                        int max = start + _numToShow;
                        if (max > _pagedDataSource.PageCount)
                        {
                            start -= max - _pagedDataSource.PageCount;
                            if (start < 0)
                            {
                                start = 0;
                            }
                            max = _pagedDataSource.PageCount;
                        }
                        if (start > 0)
                        {
                            cell = new TableCell();
                            link = new HyperLink();
                            cell.HorizontalAlign = HorizontalAlign.Left;
                            link.Text = "<<";
                            link.NavigateUrl = "javascript: __doPaginate(0);";
                            cell.Controls.Add(link);
                            lit = new Literal();
                            lit.Text = " ";
                            cell.Controls.Add(lit);
                            row.Cells.Add(cell);
                        }
                        for (int i = start; i < max; i++)
                        {
                            cell = new TableCell();
                            if (i == this._pagedDataSource.CurrentPageIndex)
                            {
                                Label lab = new Label();

                                lab.Text = (i + 1).ToString();
                                cell.Controls.Add(lab);
                                lit = new Literal();
                                lit.Text = " ";
                                cell.Controls.Add(lit);
                            }
                            else
                            {
                                link = new HyperLink();
                                cell.HorizontalAlign = HorizontalAlign.Left;
                                link.Text = (i + 1).ToString();
                                link.NavigateUrl = "javascript: __doPaginate(" + i + ");";
                                cell.Controls.Add(link);
                                lit = new Literal();
                                lit.Text = " ";
                                cell.Controls.Add(lit);
                            }
                            row.Cells.Add(cell);
                        }
                        if (max < _pagedDataSource.PageCount)
                        {
                            cell = new TableCell();
                            link = new HyperLink();
                            cell.HorizontalAlign = HorizontalAlign.Left;
                            link.Text = ">>";
                            link.NavigateUrl = "javascript: __doPaginate(" + (_pagedDataSource.PageCount - 1) + ");";
                            cell.Controls.Add(link);
                            lit = new Literal();
                            lit.Text = " ";
                            cell.Controls.Add(lit);
                            row.Cells.Add(cell);
                        }
                    }
                    break;
            }

            cell = new TableCell();
            cell.HorizontalAlign = HorizontalAlign.Right;
            cell.Width = _tableWidth;
            cell.Text = "Page " + (_pagedDataSource.CurrentPageIndex + 1) + " of " + _pagedDataSource.PageCount;
            row.Cells.Add(cell);

            table.RenderControl(writer);

            // Put the pagination controls at the top or bottom.
            base.Render(writer);
        }
    }
}