Dave Anderson, a co-worker of mine, wrote this server control that could help you get started. Note that we're targeting .NET 3.5.
[AspNetHostingPermission(
SecurityAction.Demand,
Level = AspNetHostingPermissionLevel.Minimal),
AspNetHostingPermission(SecurityAction.InheritanceDemand,
Level = AspNetHostingPermissionLevel.Minimal),
DefaultProperty("Text"),
ToolboxData("<{0}:Pager runat=\"server\"> </{0}:Pager>"),
Designer(typeof(ServerControls.Design.PagerDesigner))
]
public class Pager : WebControl, INamingContainer
{
#region Private Constants
private const string Command_First = "First";
private const string Command_Prev = "Prev";
private const string Command_Next = "Next";
private const string Command_Last = "Last";
#endregion
#region Private members
private Control PageableNamingContainer;
private PropertyInfo PageCountInfo;
private PropertyInfo PageIndexInfo;
private DropDownList ddlCurrentPage;
private Label lblPageCount;
private Button btnFirst;
private Button btnPrevious;
private Button btnNext;
private Button btnLast;
#endregion
#region Private Properties
private int PageCount
{
get
{
int Result;
if (InsideDataPager)
Result = (int)Math.Ceiling((decimal)(TotalRowCount / PageSize)) + 1;
else
Result = (int)PageCountInfo.GetValue(PageableNamingContainer, null);
return Result;
}
}
private int PageIndex
{
get
{
int Result;
if (InsideDataPager)
Result = (int)Math.Floor((decimal)(StartRowIndex / PageSize));
else
Result = (int)PageIndexInfo.GetValue(PageableNamingContainer, null);
return Result;
}
}
private int StartRowIndex
{
get
{
if (InsideDataPager)
return MyDataPager.StartRowIndex;
else
throw new Exception("DataPager functionality requires DataPager.");
}
}
private int TotalRowCount
{
get
{
if (InsideDataPager)
return MyDataPager.TotalRowCount;
else
throw new Exception("DataPager functionality requires DataPager.");
}
}
private int PageSize
{
get
{
if (InsideDataPager)
return MyDataPager.PageSize;
else
throw new Exception("DataPager functionality requires DataPager.");
}
}
private bool InsideDataPager
{
get { return ViewState["InsideDataPager"] == null ? false : (bool)ViewState["InsideDataPager"]; }
set { ViewState["InsideDataPager"] = value; }
}
#region DataPager-Specific properties
private DataPager MyDataPager
{
get
{
if (InsideDataPager)
return (DataPager)PageableNamingContainer;
else
throw new Exception("DataPager functionality requires DataPager.");
}
}
private int PrevPageStartIndex
{
get { return StartRowIndex >= PageSize ? StartRowIndex - PageSize : 0; }
}
private int NextPageStartIndex
{
get { return StartRowIndex + PageSize >= TotalRowCount ? LastPageStartIndex : StartRowIndex + PageSize; }
}
private int LastPageStartIndex
{
get { return (PageCount-1) * PageSize; }
}
#endregion
#endregion
#region Public Properties
[
Category("Behavior"),
DefaultValue(""),
Description("The stylesheet class to use for the buttons")
]
public bool HideInactiveButtons { get; set; }
[
Category("Behavior"),
DefaultValue("true"),
Description("Indicates whether the controls will invoke validation routines")
]
public bool CausesValidation { get; set; }
[
Category("Appearance"),
DefaultValue(""),
Description("The stylesheet class to use for the buttons")
]
public string ButtonCssClass { get; set; }
[
Category("Appearance"),
DefaultValue("<<"),
Description("The text to be shown on the button that navigates to the First page")
]
public string FirstText { get; set; }
[
Category("Appearance"),
DefaultValue("<"),
Description("The text to be shown on the button that navigates to the Previous page")
]
public string PreviousText { get; set; }
[
Category("Appearance"),
DefaultValue(">"),
Description("The text to be shown on the button that navigates to the Next page")
]
public string NextText { get; set; }
[
Category("Appearance"),
DefaultValue(">>"),
Description("The text to be shown on the button that navigates to the Last page")
]
public string LastText { get; set; }
#endregion
#region Overridden properties
public override ControlCollection Controls
{
get
{
EnsureChildControls();
return base.Controls;
}
}
#endregion
#region Overridden methods/events
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
if (!GetPageInfo(NamingContainer))
throw new Exception("Unable to locate the Pageable Container.");
}
protected override void OnPreRender(EventArgs e)
{
base.OnPreRender(e);
if (PageableNamingContainer != null)
{
EnsureChildControls();
ddlCurrentPage.Items.Clear();
for (int i = 0; i < PageCount; i++)
ddlCurrentPage.Items.Add(new ListItem((i + 1).ToString(), (i + 1).ToString()));
lblPageCount.Text = PageCount.ToString();
if (HideInactiveButtons)
{
btnFirst.Visible = btnPrevious.Visible = (PageIndex > 0);
btnLast.Visible = btnNext.Visible = (PageIndex < (PageCount - 1));
}
else
{
btnFirst.Enabled = btnPrevious.Enabled = (PageIndex > 0);
btnLast.Enabled = btnNext.Enabled = (PageIndex < (PageCount - 1));
}
ddlCurrentPage.SelectedIndex = PageIndex;
}
else
ddlCurrentPage.SelectedIndex = 0;
}
protected override bool OnBubbleEvent(object source, EventArgs args)
{
// We handle all our events inside this class when
// we are inside a DataPager
return InsideDataPager;
}
#endregion
#region Event delegate
protected void PagerEvent(object sender, EventArgs e)
{
if (InsideDataPager)
{
int NewStartingIndex;
if (sender.GetType() == typeof(Button))
{
string arg = ((Button)sender).CommandArgument.ToString();
switch (arg)
{
case Command_Prev:
NewStartingIndex = PrevPageStartIndex;
break;
case Command_Next:
NewStartingIndex = NextPageStartIndex;
break;
case Command_Last:
NewStartingIndex = LastPageStartIndex;
break;
case Command_First:
default:
NewStartingIndex = 0;
break;
}
}
else
{
NewStartingIndex = Math.Min(((DropDownList)sender).SelectedIndex * PageSize, LastPageStartIndex);
}
MyDataPager.SetPageProperties(NewStartingIndex, MyDataPager.MaximumRows, true);
}
else
{
CommandEventArgs ea = new CommandEventArgs("Page", ((DropDownList)sender).SelectedValue);
RaiseBubbleEvent(this, ea);
}
}
#endregion
#region GetPageableContainer
private bool GetPageInfo(Control namingContainer)
{
if (namingContainer == null || namingContainer.GetType() == typeof(Page))
throw new Exception(this.GetType().ToString() + " must be used in a pageable container like a GridView.");
/*
* NOTE: If we are inside a DataPager, this will be
* our first-level NamingContainer, so there
* will never be any reflection in that case.
*/
if (namingContainer.GetType() == typeof(DataPagerFieldItem))
{
InsideDataPager = true;
PageableNamingContainer = ((DataPagerFieldItem)namingContainer).Pager;
return true;
}
PageCountInfo = namingContainer.GetType().GetProperty("PageCount");
PageIndexInfo = namingContainer.GetType().GetProperty("PageIndex");
if (PageCountInfo == null || PageIndexInfo == null)
return GetPageInfo(namingContainer.NamingContainer);
else
{
PageableNamingContainer = namingContainer;
return true;
}
}
#endregion
#region Control generation
protected override void CreateChildControls()
{
Controls.Clear();
Controls.Add(BuildControlTable());
}
private Table BuildControlTable()
{
Table ControlTable = new Table();
ControlTable.CssClass = CssClass;
TableRow tr = new TableRow();
TableCell td = new TableCell();
td.Text = "Page";
tr.Cells.Add(td);
td = new TableCell();
ddlCurrentPage = new DropDownList();
ddlCurrentPage.ID = "ddlCurrentPage";
ddlCurrentPage.AutoPostBack = true;
ddlCurrentPage.SelectedIndexChanged += PagerEvent;
ddlCurrentPage.CausesValidation = CausesValidation;
td.Controls.Add(ddlCurrentPage);
tr.Cells.Add(td);
td = new TableCell();
td.Text = "of";
tr.Cells.Add(td);
td = new TableCell();
lblPageCount = new Label();
td.Controls.Add(lblPageCount);
tr.Cells.Add(td);
AddButton(tr, ref btnFirst, string.IsNullOrEmpty(FirstText) ? "<<" : FirstText, Command_First);
AddButton(tr, ref btnPrevious, string.IsNullOrEmpty(PreviousText) ? "<" : PreviousText, Command_Prev);
AddButton(tr, ref btnNext, string.IsNullOrEmpty(NextText) ? ">" : NextText, Command_Next);
AddButton(tr, ref btnLast, string.IsNullOrEmpty(LastText) ? ">>" : LastText, Command_Last);
ControlTable.Rows.Add(tr);
return ControlTable;
}
private void AddButton(TableRow row, ref Button button, string text, string argument)
{
button = new Button();
button.Text = text;
button.CssClass = ButtonCssClass;
button.CommandName = "Page";
button.CommandArgument = argument;
button.CausesValidation = CausesValidation;
if (InsideDataPager)
button.Click += PagerEvent;
TableCell td = new TableCell();
td.Controls.Add(button);
row.Cells.Add(td);
}
#endregion
}