模仿MS PetShop重写了Repeater控件,使其具有分页功能。
.cs
.aspx
.aspx.cs
其实和PetShop里的差不多,就加强了一点分页功能。
.cs
using System;
using System.Data;
using System.Collections;
using System.Text.RegularExpressions;
using System.Web.UI.WebControls;
namespace Common.WebControls
{
public class MyRepeater : Repeater
{
//常量
protected const string HTML1 = "<table cellpadding=0 cellspacing=0><tr><td align={0} class=pageHeader>";
protected const string HTML2 = "</td></tr><tr class=gridNav><td>";
protected const string HTML3 = "</td></tr><tr><td align={0} class=pageFooter>";
protected const string HTML4 = "</td></tr></table>";
private const string LINK = "<a href=?{0}={1} class=pageLink>{2}</a>";
private const string LINK_NEXT = "<a href=?{0}={1} title='下{2}页' class=pageLink>{3}</a>";
private const string LINK_PREV = "<a href=?{0}={1} title='上{2}页' class=pageLink>{3}</a>";
//私有变量
private string mstrEmptyText = "";//DataSource为空的时候显示的字
private string mstrPageKey = "Page";//在地址栏上显示的页码关键字,比如page=1
private string mstrPageIndexAlign = "right";//页码对齐方式
private string mstrPrevPageText = "<<";//上页文字
private string mstrNextPageText = ">>";//下页文字
private PagerPosition pagePosition = PagerPosition.TopAndBottom;//页码位置,上、下、上下都有
private PagerMode pageMode = PagerMode.NumericPages;//页导航元素模式
private int intPageIndexCount = 10;//显示的页码数
private int intPageSize = 10;//一页显示的记录数
private int intCurrentPage = 1;//当前页
private IList dataSource;//数据源,必须可以转换为IList
private bool blnRealSource = false;//数据源已分页
private int intItemCount;
/// <summary>
/// 数据源为空时显示的文本,默认为空
/// </summary>
public string EmptyText
{
set { mstrEmptyText = value; }
}
public bool RealSource
{
get { return blnRealSource; }
set { blnRealSource = value; }
}
/// <summary>
/// 获取或设置自定义地址栏上页码标志关键字,默认为Page。
/// 如果页面有两个MyRepeater,必须定义两个不同的PageKey。
/// 否则不能正确定位第二个MyRepeater。
/// </summary>
public string PageKey
{
get { return mstrPageKey; }
set { mstrPageKey = value; }
}
/// <summary>
/// 获取或设置要在 MyRepeater 控件的单页上显示的项数。
/// 默认为10项。
/// </summary>
public int PageSize
{
get { return intPageSize; }
set { intPageSize = value; }
}
/// <summary>
/// 获取或设置当前显示页的索引。默认为1。
/// </summary>
public int CurrentPageIndex
{
get { return intCurrentPage; }
set {intCurrentPage = value; }
}
/// <summary>
/// 获取或设置 MyRepeater 控件中页导航元素的位置。
/// 默认为 TopAndBottom。
/// </summary>
public PagerPosition PagePosition
{
get { return pagePosition; }
set { pagePosition = value; }
}
/// <summary>
/// 获取或设置一个值,该值指定页导航元素是显示链接到下一页和前一页的按钮,还是显示直接与某一页链接的数值按钮。
/// 默认为 NumericPages。
/// </summary>
public PagerMode PageMode
{
get { return pageMode; }
set { pageMode = value; }
}
/// <summary>
/// 获取 MyRepeater 控件中页导航元素的对齐方式。
/// 默认为right。
/// </summary>
public HorizontalAlign PageAlign
{
set { mstrPageIndexAlign = value.ToString(); }
}
/// <summary>
/// 获取或设置为前一页按钮显示的文本。
/// </summary>
public string PrevPageText
{
get { return mstrPrevPageText; }
set { mstrPrevPageText = value; }
}
/// <summary>
/// 获取或设置为下一页按钮显示的文本。
/// </summary>
public string NextPageText
{
get { return mstrNextPageText; }
set { mstrNextPageText = value; }
}
/// <summary>
/// 获取显示 MyRepeater 控件中各项所需的总页数。
/// </summary>
public int PageCount
{
get { return (intItemCount - 1) / intPageSize + 1; }
}
/// <summary>
/// 设置 MyRepeater 控件中页导航元素显示的页码数。
/// 默认为10。
/// </summary>
public int PageIndexCount
{
set { intPageIndexCount = value; }
}
/// <summary>
/// 设置 MyRepeater 控件的数据源。
/// 可以接受 DataSet、DataTable和所以实现了IList借口的数据源。
/// </summary>
public override object DataSource
{
set
{
try
{
if(value == null)
{
dataSource = null;
intItemCount = 0;
}
else if(value.GetType() == typeof(DataTable))//数据源是DataTable,转化为IList
{
dataSource = (IList)(new DataView((DataTable)value));
intItemCount = dataSource.Count;
}
else if(value.GetType() == typeof(DataSet))//数据源是DataSet,转化为IList
{
dataSource = (IList)(new DataView(((DataSet)value).Tables[0]));
intItemCount = dataSource.Count;
}
else
{
dataSource = (IList)value;
intItemCount = dataSource.Count;
}
}
catch
{
dataSource = null;
intItemCount =0;
}
}
}
protected override void OnLoad(EventArgs e)
{
if(Visible)
{
string page = Context.Request[mstrPageKey];//取得页码
int index = (page != null) ? int.Parse(page) : 1;
index = index <= 0 ? 1 : index;
SetPage(index);
}
}
public void SetPage(int index)
{
OnPageIndexChanged(new DataGridPageChangedEventArgs(null, index));
}
protected override void Render(System.Web.UI.HtmlTextWriter writer)
{
if(intItemCount == 0)//数据源为空
{
writer.Write(mstrEmptyText);
return;
}
writer.Write(HTML1, mstrPageIndexAlign);
if(pagePosition != PagerPosition.Bottom)//页导航元素的位置为Top或者TopAndBottom
{
WritePages(writer);
}
writer.Write(HTML2);
base.Render(writer);
writer.Write(HTML3, mstrPageIndexAlign);
if(pagePosition != PagerPosition.Top)//页导航元素的位置为Bottom或者TopAndBottom
{
WritePages(writer);
}
writer.Write(HTML4);
}
protected override void OnDataBinding(EventArgs e)
{
if(blnRealSource)//数据源已分页
{
base.DataSource = dataSource;
}
else//数据源未分页
{
int start = (intCurrentPage - 1) * intPageSize;
int size = Math.Min(intPageSize, intItemCount - start);
IList list = new ArrayList();
for(int i = 0; i < size; i++)
{
list.Add(dataSource[start + i]);
}
base.DataSource = list;
}
base.OnDataBinding (e);
}
public event DataGridPageChangedEventHandler PageIndexChanged;
virtual protected void OnPageIndexChanged(DataGridPageChangedEventArgs e)
{
if (PageIndexChanged != null)
{
PageIndexChanged(this, e);
}
}
/// <summary>
/// 写页导航元素。
/// </summary>
/// <param name="writer">System.Web.UI.HtmlTextWriter</param>
virtual protected void WritePages(System.Web.UI.HtmlTextWriter writer)
{
if(pageMode == PagerMode.NextPrev)//页导航元素为上下页
{
intPageIndexCount = 1;
}
intPageIndexCount = intPageIndexCount <= 0 ? 1 : intPageIndexCount;
//开始的页码
int start = (intCurrentPage - 1) / intPageIndexCount;
start = start * intPageIndexCount + 1;
//结束的页码
int end = start + intPageIndexCount - 1;
end = end > PageCount ? PageCount : end;
//保留PageKey以外的QueryString
string query = Context.Request.Url.Query.Replace("?","&");
Regex rx = new Regex("&" + mstrPageKey + "=\d+", RegexOptions.None);
query = rx.Replace(query, string.Empty);
//写向前的导航元素
if(start > 1)
{
writer.Write(LINK_PREV, mstrPageKey, (start - 1) + query, intPageIndexCount, mstrPrevPageText);
}
if(pageMode != PagerMode.NextPrev)//页导航元素为上下页
{
//写从start到end的页码
for(int i = start; i <= end; i++)
{
writer.Write(" ");
if(i == intCurrentPage)//当前页没有联接
{
writer.Write(i);
}
else//不是当前页有链接
{
writer.Write(LINK, mstrPageKey, i + query, i);
}
}
}
//写向后的导航元素
if(end < PageCount)
{
writer.Write(" ");
writer.Write(LINK_NEXT, mstrPageKey, (end + 1) + query, intPageIndexCount, mstrNextPageText);
}
}
}
}
using System.Data;
using System.Collections;
using System.Text.RegularExpressions;
using System.Web.UI.WebControls;
namespace Common.WebControls
{
public class MyRepeater : Repeater
{
//常量
protected const string HTML1 = "<table cellpadding=0 cellspacing=0><tr><td align={0} class=pageHeader>";
protected const string HTML2 = "</td></tr><tr class=gridNav><td>";
protected const string HTML3 = "</td></tr><tr><td align={0} class=pageFooter>";
protected const string HTML4 = "</td></tr></table>";
private const string LINK = "<a href=?{0}={1} class=pageLink>{2}</a>";
private const string LINK_NEXT = "<a href=?{0}={1} title='下{2}页' class=pageLink>{3}</a>";
private const string LINK_PREV = "<a href=?{0}={1} title='上{2}页' class=pageLink>{3}</a>";
//私有变量
private string mstrEmptyText = "";//DataSource为空的时候显示的字
private string mstrPageKey = "Page";//在地址栏上显示的页码关键字,比如page=1
private string mstrPageIndexAlign = "right";//页码对齐方式
private string mstrPrevPageText = "<<";//上页文字
private string mstrNextPageText = ">>";//下页文字
private PagerPosition pagePosition = PagerPosition.TopAndBottom;//页码位置,上、下、上下都有
private PagerMode pageMode = PagerMode.NumericPages;//页导航元素模式
private int intPageIndexCount = 10;//显示的页码数
private int intPageSize = 10;//一页显示的记录数
private int intCurrentPage = 1;//当前页
private IList dataSource;//数据源,必须可以转换为IList
private bool blnRealSource = false;//数据源已分页
private int intItemCount;
/// <summary>
/// 数据源为空时显示的文本,默认为空
/// </summary>
public string EmptyText
{
set { mstrEmptyText = value; }
}
public bool RealSource
{
get { return blnRealSource; }
set { blnRealSource = value; }
}
/// <summary>
/// 获取或设置自定义地址栏上页码标志关键字,默认为Page。
/// 如果页面有两个MyRepeater,必须定义两个不同的PageKey。
/// 否则不能正确定位第二个MyRepeater。
/// </summary>
public string PageKey
{
get { return mstrPageKey; }
set { mstrPageKey = value; }
}
/// <summary>
/// 获取或设置要在 MyRepeater 控件的单页上显示的项数。
/// 默认为10项。
/// </summary>
public int PageSize
{
get { return intPageSize; }
set { intPageSize = value; }
}
/// <summary>
/// 获取或设置当前显示页的索引。默认为1。
/// </summary>
public int CurrentPageIndex
{
get { return intCurrentPage; }
set {intCurrentPage = value; }
}
/// <summary>
/// 获取或设置 MyRepeater 控件中页导航元素的位置。
/// 默认为 TopAndBottom。
/// </summary>
public PagerPosition PagePosition
{
get { return pagePosition; }
set { pagePosition = value; }
}
/// <summary>
/// 获取或设置一个值,该值指定页导航元素是显示链接到下一页和前一页的按钮,还是显示直接与某一页链接的数值按钮。
/// 默认为 NumericPages。
/// </summary>
public PagerMode PageMode
{
get { return pageMode; }
set { pageMode = value; }
}
/// <summary>
/// 获取 MyRepeater 控件中页导航元素的对齐方式。
/// 默认为right。
/// </summary>
public HorizontalAlign PageAlign
{
set { mstrPageIndexAlign = value.ToString(); }
}
/// <summary>
/// 获取或设置为前一页按钮显示的文本。
/// </summary>
public string PrevPageText
{
get { return mstrPrevPageText; }
set { mstrPrevPageText = value; }
}
/// <summary>
/// 获取或设置为下一页按钮显示的文本。
/// </summary>
public string NextPageText
{
get { return mstrNextPageText; }
set { mstrNextPageText = value; }
}
/// <summary>
/// 获取显示 MyRepeater 控件中各项所需的总页数。
/// </summary>
public int PageCount
{
get { return (intItemCount - 1) / intPageSize + 1; }
}
/// <summary>
/// 设置 MyRepeater 控件中页导航元素显示的页码数。
/// 默认为10。
/// </summary>
public int PageIndexCount
{
set { intPageIndexCount = value; }
}
/// <summary>
/// 设置 MyRepeater 控件的数据源。
/// 可以接受 DataSet、DataTable和所以实现了IList借口的数据源。
/// </summary>
public override object DataSource
{
set
{
try
{
if(value == null)
{
dataSource = null;
intItemCount = 0;
}
else if(value.GetType() == typeof(DataTable))//数据源是DataTable,转化为IList
{
dataSource = (IList)(new DataView((DataTable)value));
intItemCount = dataSource.Count;
}
else if(value.GetType() == typeof(DataSet))//数据源是DataSet,转化为IList
{
dataSource = (IList)(new DataView(((DataSet)value).Tables[0]));
intItemCount = dataSource.Count;
}
else
{
dataSource = (IList)value;
intItemCount = dataSource.Count;
}
}
catch
{
dataSource = null;
intItemCount =0;
}
}
}
protected override void OnLoad(EventArgs e)
{
if(Visible)
{
string page = Context.Request[mstrPageKey];//取得页码
int index = (page != null) ? int.Parse(page) : 1;
index = index <= 0 ? 1 : index;
SetPage(index);
}
}
public void SetPage(int index)
{
OnPageIndexChanged(new DataGridPageChangedEventArgs(null, index));
}
protected override void Render(System.Web.UI.HtmlTextWriter writer)
{
if(intItemCount == 0)//数据源为空
{
writer.Write(mstrEmptyText);
return;
}
writer.Write(HTML1, mstrPageIndexAlign);
if(pagePosition != PagerPosition.Bottom)//页导航元素的位置为Top或者TopAndBottom
{
WritePages(writer);
}
writer.Write(HTML2);
base.Render(writer);
writer.Write(HTML3, mstrPageIndexAlign);
if(pagePosition != PagerPosition.Top)//页导航元素的位置为Bottom或者TopAndBottom
{
WritePages(writer);
}
writer.Write(HTML4);
}
protected override void OnDataBinding(EventArgs e)
{
if(blnRealSource)//数据源已分页
{
base.DataSource = dataSource;
}
else//数据源未分页
{
int start = (intCurrentPage - 1) * intPageSize;
int size = Math.Min(intPageSize, intItemCount - start);
IList list = new ArrayList();
for(int i = 0; i < size; i++)
{
list.Add(dataSource[start + i]);
}
base.DataSource = list;
}
base.OnDataBinding (e);
}
public event DataGridPageChangedEventHandler PageIndexChanged;
virtual protected void OnPageIndexChanged(DataGridPageChangedEventArgs e)
{
if (PageIndexChanged != null)
{
PageIndexChanged(this, e);
}
}
/// <summary>
/// 写页导航元素。
/// </summary>
/// <param name="writer">System.Web.UI.HtmlTextWriter</param>
virtual protected void WritePages(System.Web.UI.HtmlTextWriter writer)
{
if(pageMode == PagerMode.NextPrev)//页导航元素为上下页
{
intPageIndexCount = 1;
}
intPageIndexCount = intPageIndexCount <= 0 ? 1 : intPageIndexCount;
//开始的页码
int start = (intCurrentPage - 1) / intPageIndexCount;
start = start * intPageIndexCount + 1;
//结束的页码
int end = start + intPageIndexCount - 1;
end = end > PageCount ? PageCount : end;
//保留PageKey以外的QueryString
string query = Context.Request.Url.Query.Replace("?","&");
Regex rx = new Regex("&" + mstrPageKey + "=\d+", RegexOptions.None);
query = rx.Replace(query, string.Empty);
//写向前的导航元素
if(start > 1)
{
writer.Write(LINK_PREV, mstrPageKey, (start - 1) + query, intPageIndexCount, mstrPrevPageText);
}
if(pageMode != PagerMode.NextPrev)//页导航元素为上下页
{
//写从start到end的页码
for(int i = start; i <= end; i++)
{
writer.Write(" ");
if(i == intCurrentPage)//当前页没有联接
{
writer.Write(i);
}
else//不是当前页有链接
{
writer.Write(LINK, mstrPageKey, i + query, i);
}
}
}
//写向后的导航元素
if(end < PageCount)
{
writer.Write(" ");
writer.Write(LINK_NEXT, mstrPageKey, (end + 1) + query, intPageIndexCount, mstrNextPageText);
}
}
}
}
.aspx
<MYCONTROL:MYREPEATER id="repeater" runat="server" PageKey="Pages" OnPageIndexChanged="PageChanged" EmptyText="nothing">
<headertemplate>
<table cellpadding="0" cellspacing="0">
<tr class="gridHead">
<td>Product</td>
<td>Name</td>
<td>Description</td>
</tr>
</headertemplate>
<itemtemplate>
<tr class="gridItem">
<td><%# DataBinder.Eval(Container.DataItem, "Id") %></td>
<td><a href='Items.aspx?productId=<%# DataBinder.Eval(Container.DataItem, "Id") %>'><%# DataBinder.Eval(Container.DataItem, "Name") %></a></td>
<td><%# DataBinder.Eval(Container.DataItem, "Description") %></td>
</tr>
</itemtemplate>
<footertemplate>
</table>
</footertemplate>
</MYCONTROL:MYREPEATER>
<headertemplate>
<table cellpadding="0" cellspacing="0">
<tr class="gridHead">
<td>Product</td>
<td>Name</td>
<td>Description</td>
</tr>
</headertemplate>
<itemtemplate>
<tr class="gridItem">
<td><%# DataBinder.Eval(Container.DataItem, "Id") %></td>
<td><a href='Items.aspx?productId=<%# DataBinder.Eval(Container.DataItem, "Id") %>'><%# DataBinder.Eval(Container.DataItem, "Name") %></a></td>
<td><%# DataBinder.Eval(Container.DataItem, "Description") %></td>
</tr>
</itemtemplate>
<footertemplate>
</table>
</footertemplate>
</MYCONTROL:MYREPEATER>
.aspx.cs
protected void PageChanged(object sender, DataGridPageChangedEventArgs e)
{
Common.WebControls.MyRepeater re = sender as Common.WebControls.MyRepeater;
re.CurrentPageIndex = e.NewPageIndex;
DataTable dt = new DataTable();
dt.Columns.Add("Id");
dt.Columns.Add("Name");
dt.Columns.Add("Description");
for(int i = 0; i < 350; i++)
{
DataRow dr = dt.NewRow();
dr[0] = i.ToString();
dr[1] = "testName";
dr[2] = "testDescription";
dt.Rows.Add(dr);
}
re.PrevPageText = "上 页";
re.NextPageText = "下 页";
re.PageMode = PagerMode.NextPrev;
re.PageAlign = HorizontalAlign.Right;
re.PagePosition = PagerPosition.Bottom;
re.PageSize = 20;
re.DataSource = dt;
re.DataBind();
}
{
Common.WebControls.MyRepeater re = sender as Common.WebControls.MyRepeater;
re.CurrentPageIndex = e.NewPageIndex;
DataTable dt = new DataTable();
dt.Columns.Add("Id");
dt.Columns.Add("Name");
dt.Columns.Add("Description");
for(int i = 0; i < 350; i++)
{
DataRow dr = dt.NewRow();
dr[0] = i.ToString();
dr[1] = "testName";
dr[2] = "testDescription";
dt.Rows.Add(dr);
}
re.PrevPageText = "上 页";
re.NextPageText = "下 页";
re.PageMode = PagerMode.NextPrev;
re.PageAlign = HorizontalAlign.Right;
re.PagePosition = PagerPosition.Bottom;
re.PageSize = 20;
re.DataSource = dt;
re.DataBind();
}
其实和PetShop里的差不多,就加强了一点分页功能。