一直以来对分页技术的研究都没有停止过。但是怎样实现良好的分页功能?本人认为要看具体的应用场景。如:论坛,产品列表,搜索结果,软件中的报表等等,每个应用场景都有它的特点,当然采用的分页技术也应该有所区别,不管应用场景去谈分页技术无异于“闭门造车”。具体在那些环境下应该采用什么样的分页技术,本次将不再赘述,有兴趣的朋友我们可以后面继续讨论。这里我提供一个自己写的非常简单的几个分页控件的源代码给大家参考。当然这个控件也不是什么情况下都好用。我只是提供一个简单范例。
当然实现方法很多,我这里是override DataSource属性(我觉得这个方法针对我目前的应用已经足够了,因为我毕竟不是卖控件的)
1。我们先来定义一个interface(因为我作了好几个控件,哈哈)
public interface IDataPreviewControl
{
int PageIndex { get; set;}
int PageCount { get;}
int RowCount { get;}
int StartRowIndex { get; }
int EndRowIndex { get; }
int PageSize { get; set; }
int CurrentPageIndex { set; }
bool isFirstPage { get; }
bool isLastPage { get; }
}
2。下面来写一个iReapter(继承自Repeater)
[DefaultProperty("PageIndex")]
[ToolboxData("<{0}:iRepeater runat=server></{0}:iRepeater>")]
public class iRepeater : Repeater, IDataPreviewControl
{
#region Properties
public bool AllowPaging
{
get
{
if (this.ViewState["_AllowPaging"] == null)
{
this.ViewState["_AllowPaging"] = true;
}
return (bool)this.ViewState["_AllowPaging"];
}
set {
this.ViewState["_AllowPaging"] = value;
}
}
/// <summary>
/// 當前頁索引
/// </summary>
public int PageIndex
{
get
{
if (this.ViewState["_PageIndex"] == null)
{
this.ViewState["_PageIndex"] = 0;
}
int _PageIndex = (int)this.ViewState["_PageIndex"];
if (_PageIndex > this.PageCount - 1)
{
_PageIndex = this.PageCount - 1;
}
else if (_PageIndex < 0)
{
_PageIndex = 0;
}
this.ViewState["_PageIndex"] = _PageIndex;
return (int)this.ViewState["_PageIndex"];
}
set
{
int _PageIndex = value;
this.ViewState["_PageIndex"] = _PageIndex;
}
}
public int CurrentPageIndex
{
set
{
this.PageIndex = value;
}
}
public int PageCount
{
get
{
if (this.ViewState["_TotalPageCount"] == null)
{
this.ViewState["_TotalPageCount"] = 1;
}
return (int)this.ViewState["_TotalPageCount"];
}
}
public int RowCount
{
get
{
if (this.ViewState["_TotalRowCount"] == null)
{
this.ViewState["_TotalRowCount"] = 1;
}
return (int)this.ViewState["_TotalRowCount"];
}
}
public int StartRowIndex
{
get
{
return this.PageIndex * this.PageSize;
}
}
public int EndRowIndex
{
get
{
if (this.PageIndex == this.PageCount - 1)
{
return this.RowCount;
}
else
{
return this.StartRowIndex + this.PageSize;
}
}
}
public int PageSize
{
get
{
if (this.ViewState["_pageSize"] == null)
{
this.ViewState["_pageSize"] = 10;
}
return (int)this.ViewState["_pageSize"];
}
set { this.ViewState["_pageSize"] = value; }
}
public bool isFirstPage
{
get
{
return (this.PageIndex == 0);
}
}
public bool isLastPage
{
get
{
return (this.PageIndex == this.PageCount - 1);
}
}
public override object DataSource
{
get
{
return base.DataSource;
}
set
{
if (value != null)
{
if (this.AllowPaging)
{
System.Data.DataView dv = (System.Data.DataView)value;
PagedDataSource Pds = new PagedDataSource();
Pds.DataSource = dv;
Pds.AllowPaging = true;
Pds.PageSize = this.PageSize;
this.ViewState["_TotalPageCount"] = Pds.PageCount;
this.ViewState["_TotalRowCount"] = dv.Count;
this.ViewState["_StartRowIndex"] = Pds.FirstIndexInPage;
this.ViewState["_isFirstPage"] = Pds.IsFirstPage;
this.ViewState["_isLastPage"] = Pds.IsLastPage;
Pds.CurrentPageIndex = this.PageIndex;
base.DataSource = Pds;
}
else {
base.DataSource = value;
}
}
else
{
base.DataSource = null;
}
}
}
3。定义一个简单的iDataPager,用来驱动iRepeater翻页,这里我定义了一个iPageEventArgs,用来模仿GridView的分页
[DefaultProperty("Buttons")]
[DefaultEvent("selectedPageIndex")]
[ToolboxData("<{0}:iDataPager runat=server></{0}:iDataPager>")]
public class iDataPager : WebControl,IPostBackEventHandler
{
public int StartRowIndex
{
get
{
return this.DataPreviewControl.StartRowIndex;
}
}
public int EndRowIndex
{
get
{
return this.StartRowIndex + this.DataPreviewControl.PageSize;
}
}
public int PageSize
{
get
{
return this.DataPreviewControl.PageSize;
}
}
public bool isFirstPage
{
get
{
return (this.DataPreviewControl.PageIndex==0);
}
}
public bool isLastPage
{
get
{
return (this.DataPreviewControl.PageIndex == this.DataPreviewControl.PageCount-1);
}
}
private int totalPages = 0;
protected override void Render(HtmlTextWriter writer)
{
if (!this.DesignMode)
{
StringBuilder sb = new StringBuilder();
sb.Append("<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" class=\""+this.CssClass+"\">");
sb.Append("<tr>");
// First
sb.Append("<td>");
if (this.isFirstPage)
{
sb.Append("<div disabled>|<</div>");
}
else {
sb.Append("<a href=\"#\" onclick=\"" + this.Page.ClientScript.GetPostBackEventReference(this, "0") + "\">|<</a>");
}
sb.Append("</td>");
// Previous
sb.Append("<td>");
if (this.isFirstPage)
{
sb.Append("<div disabled><</div>");
}
else {
sb.Append("<a href=\"#\" onclick=\"" + this.Page.ClientScript.GetPostBackEventReference(this, (this.DataPreviewControl.PageIndex - 1).ToString()) + "\"><</a>");
}
sb.Append("</td>");
if (this.DataPreviewControl!=null)
{
int startPageBtn = 0;
int endPageBtn = 0;
this.totalPages = Convert.ToInt32(this.DataPreviewControl.PageCount / this.Buttons) + (this.DataPreviewControl.PageCount % this.Buttons==0 ? 0 : 1);
for (int j = 1; j <= this.totalPages ; j++)
{
endPageBtn = j * this.Buttons;
startPageBtn = endPageBtn - this.Buttons + 1;
int k=this.DataPreviewControl.PageIndex+1;
if (k >= startPageBtn && k <= endPageBtn)
{
break;
}
}
if (endPageBtn > this.DataPreviewControl.PageCount)
{
endPageBtn = this.DataPreviewControl.PageCount;
}
for (int i = startPageBtn; i <= endPageBtn; i++)
{
sb.Append("<td>");
if (this.DataPreviewControl.PageIndex == (i - 1))
{
sb.Append("<span>" + i.ToString() + "</span>");
}
else {
sb.Append("<a href=\"#\" onclick=\"" + this.Page.ClientScript.GetPostBackEventReference(this,(i-1).ToString()) + "\">" + i.ToString() + "</a>");
}
sb.Append("</td>");
}
if (endPageBtn < this.DataPreviewControl.PageCount)
{
// More...
sb.Append("<td>");
sb.Append("<a href=\"#\" onclick=\"" + this.Page.ClientScript.GetPostBackEventReference(this, endPageBtn.ToString()) + "\">...</a>");
sb.Append("</td>");
}
}
// Next
sb.Append("<td>");
if (this.isLastPage)
{
sb.Append("<div disabled>></div>");
}
else {
sb.Append("<a href=\"#\" onclick=\"" + this.Page.ClientScript.GetPostBackEventReference(this, (this.DataPreviewControl.PageIndex + 1).ToString()) + "\">></a>");
}
sb.Append("</td>");
// Last
sb.Append("<td>");
if (this.isLastPage)
{
sb.Append("<div disabled>>|</div>");
}
else {
sb.Append("<a href=\"#\" onclick=\"" + this.Page.ClientScript.GetPostBackEventReference(this, (this.DataPreviewControl.PageCount - 1).ToString()) + "\">>|</a>");
}
sb.Append("</td>");
sb.Append("</tr>");
sb.Append("</table>");
writer.Write(sb.ToString());
sb = null;
}
base.Render(writer);
}
private IDataPreviewControl _ControlID=null;
public IDataPreviewControl DataPreviewControl
{
get { return _ControlID; }
set { _ControlID = value; }
}
protected override HtmlTextWriterTag TagKey
{
get
{
return HtmlTextWriterTag.Div;
}
}
public int Buttons
{
get
{
if (this.ViewState["_Buttons"] == null)
{
this.ViewState["_Buttons"] = 10;
}
return (int)this.ViewState["_Buttons"];
}
set { this.ViewState["_Buttons"] = value; }
}
public void RaisePostBackEvent(string eventArgument)
{
this.OnSelectedPageIndex(new iPageEventArgs(this.NewPageIndex));
}
protected virtual void OnSelectedPageIndex(iPageEventArgs e)
{
if (selectedPageIndex != null)
{
selectedPageIndex(this, e);
}
}
public delegate void EventHandler(Object sender, iPageEventArgs e);
public event EventHandler selectedPageIndex;
public int NewPageIndex
{
get
{
return Convert.ToInt32(this.Page.Request.Form["__EVENTARGUMENT"]);
}
}
}
public class iPageEventArgs : EventArgs
{
public iPageEventArgs(int _NewPageIndex)
{
_NewPageIndex2 = _NewPageIndex;
}
private int _NewPageIndex2 = 0;
public int NewPageIndex
{
get { return _NewPageIndex2; }
}
}
4。调用范例
///在Page_load中初始化
protected void Page_Load(object sender, EventArgs e)
{
this.IDataPager1.DataPreviewControl = this.iRepaeater1;
this.IDataPager1.Buttons = 10;
this.iRepaeater1.PageSize = 15;
}
// 类似于GridView的翻页
protected void IDataPager1_selectedPageIndex(object sender, iPageEventArgs e)
{
this.iRepaeater1.PageIndex = e.NewPageIndex;
//给iRepaeater1邦定数据
DataTable dt=new DataTable();
///...给DataTable数据
this.iRepaeater1.DataSource=dt.DefaultView;
this.iRepaeater1.DataBind();
}