前两天看了一个自定义分页控件,和AspNetPager一样是实现IPostBackEventHandler接口,不过简洁许多,就想能不能实现ICallbackEventHandler接口做到无刷新分页呢?想到了就马上去做,终于,设想变成了现实!!
个人喜欢用Repeater,因其简洁,此AjaxPager定向为Repeater!
一步一步看来:
ToolboxData( " <{0}:AjaxPager runat=server></{0}:AjaxPager> " )]
public class AjaxPager : WebControl,ICallbackEventHandler
{
public AjaxPager()
: base (HtmlTextWriterTag.Div)
{
this .Load += new EventHandler(AjaxPager_Load);
}
void AjaxPager_Load( object sender, EventArgs e)
{
string script = " function AjaxPagerCallBack(returnData){var parts =returnData.split('[_]'); document.getElementById(' " + this .UniqueID.Replace ( ' $ ' , ' _ ' ) + " ').innerHTML = parts[0];document.getElementById(' " + Info.ContainID + " ').innerHTML=parts[1]} " ;
this .Page.ClientScript.RegisterClientScriptBlock( this .Page.GetType(), " AjaxPagerCallBack " , script, true );
}
}
这里在Load事件里向页面注册了一段JS,AjaxPagerCallBack方法做两个操作,把自己表现的数据放入自己在客户端生成的DIV容器里,即id为this.UniqueID.Replace('$','_')的div,ClientID好像也可以!哈,一时糊涂!第二步就是把分页数据放到id为Info.ContainID的div中,Info对象下面会说到。
private string _BarBackGroundColor = " #FFFFFF " ;
private string _BarLinkColor = " Navy " ;
private string _BarCurrentColor = " #EEEEEE " ;
private int _TotalRecord = 50 ;
private int _TotalPage = 0 ;
private int _CurrentIndex = 1 ;
private int _ItemSize = 10 ;
private PageInfo _Info = new PageInfo ();
#endregion
#region 属性
#region 外观
[Description( " 分页背景色 " ),
Bindable( true ),
Category( " 外观 " ),
DefaultValue( " #FFFFFF " )]
public string BarBackGroundColor
{
get { return _BarBackGroundColor; }
set { _BarBackGroundColor = value; }
}
[Description( " 分页条链接数字颜色 " ),
Bindable( true ),
Category( " 外观 " ),
DefaultValue( " Navy " )]
public string BarLinkColor
{
get { return _BarLinkColor; }
set { _BarLinkColor = value; }
}
[Description( " 分页条当前页数字颜色 " ),
Bindable( true ),
Category( " 外观 " ),
DefaultValue( " #EEEEEE " )]
public string BarCurrentColor
{
get { return _BarCurrentColor; }
set { _BarCurrentColor = value; }
}
#endregion
#region 行为
[Description( " 总记录数 " ),
Category( " 行为 " ),
DefaultValue( 50 )]
public int TotalRecord
{
get { return _TotalRecord; }
set
{
_TotalRecord = value;
}
}
[Description( " 总页数 " ),
Category( " 行为 " ),
DefaultValue( 0 )]
public int TotalPage
{
get { return _TotalPage; }
}
[Description( " Bar的大小 " ),
Category( " 行为 " ),
DefaultValue( 10 )]
public int BarSize
{
get { return _ItemSize; }
set
{
foreach ( char c in System.Convert.ToString(value))
{
if ( ! Char.IsNumber(c))
{
_ItemSize = 10 ;
break ;
}
}
_ItemSize = value;
}
}
[Description( " 当前页值 " ),
Category( " 行为 " ),
DefaultValue( 1 )]
public int PageIndex
{
get { return _CurrentIndex; }
set { _CurrentIndex = value; }
}
#endregion
public PageInfo Info
{
get { return _Info; }
set { _Info = value; }
}
#endregion
这里自不必细说。其中的PageInfo如下:
public class PageInfo
{
private string _RepeaterUniqueID;
private string _ContainID = " AjaxData " ;
private string _TableName = string .Empty;
private string _IdentityField = " ID " ;
private int _PageSize = 10 ;
private string _Fields = " * " ;
private bool _IsDesc = true ;
private string _Content = string .Empty;
private string _ConnectStringName = string .Empty;
public string RepeaterUniqueID
{
get { return _RepeaterUniqueID; }
set { _RepeaterUniqueID = value; }
}
public string ContainID
{
get { return _ContainID; }
set { _ContainID = value; }
}
public int PageSize
{
get { return _PageSize; }
set
{
_PageSize = int .Parse(value.ToString());
}
}
public string TableName
{
get { return _TableName; }
set { _TableName = value; }
}
public string IdentityField
{
get { return _IdentityField; }
set { _IdentityField = value; }
}
public string Fields
{
get { return _Fields; }
set { _Fields = value; }
}
public bool IsDesc
{
get { return _IsDesc; }
set { _IsDesc = value; }
}
public string Content
{
get { return _Content; }
set { _Content = value; }
}
public string ConnectStringName
{
get { return _ConnectStringName; }
set { _ConnectStringName = value; }
}
}
这是标记为Serializable,是因为下面要保存到ViewState里。
{
this ._TotalPage = (( this .TotalRecord / this .Info.PageSize) * this .Info.PageSize == this .TotalRecord) ? ( this .TotalRecord / this .Info.PageSize) : (( this .TotalRecord / this .Info.PageSize) + 1 );
int BeginRecord = ( this .PageIndex - 1 ) * this .Info.PageSize + 1 ;
int EndRecord = Math.Min( this .PageIndex * this .Info.PageSize, this .TotalRecord);
string PageInfo = string .Format( " [每页<span style='color:#CC0000'>{0}({1}-{2})</span>条 共<span style='color:#CC0000'>{3}</span>条<span style='color:#CC0000'>{4}</span>页] " , Info.PageSize, BeginRecord, EndRecord, this .TotalRecord, this .TotalPage);
StringBuilder PageListStr = new StringBuilder();
string PageIndexColor = " #000000 " ;
int SingleNumber = this .TotalPage - (TotalPage / BarSize) * BarSize;
int IntPageForMax = ( this .PageIndex - 1 ) / BarSize;
int MinInt = ( 1 + BarSize * IntPageForMax);
int MaxInt = ((IntPageForMax + 1 ) * BarSize) > TotalPage ? TotalPage : ((IntPageForMax + 1 ) * BarSize);
if ( this .TotalRecord == 0 || this .TotalPage == 0 )
{
PageListStr.AppendFormat( " <span style='color:'{0};margin:auto 3px;'>0</span> " , PageIndexColor);
PageListStr.AppendFormat( " [共<span style='color:#CC0000'>0</span>页/当前第<span style='color:#CC0000'>0</span>页 共<span style='color:#CC0000'>0</span>条记录,当前记录数<span style='color:#CC0000'>0</span>到<span style='color:#CC0000'>0</span>] " );
return PageListStr.ToString();
}
else
{
if ( this .TotalPage <= this .BarSize)
{
for ( int i = 1 ; i <= TotalPage; i ++ )
{
PageIndexColor = PageIndex == i ? " #CC0000 " : " #000000 " ;
if (PageIndex == i)
PageListStr.AppendFormat( " <a id='{0}' style='color:{1};margin:auto 3px;'>{2}</a> " , this .UniqueID, PageIndexColor, i);
else
PageListStr.AppendFormat( " <a id='{0}' style='color:{1};margin:auto 3px;' href=\ " javascript:{ 2 }\ " >{3}</a> " , this .UniqueID, PageIndexColor, Page.ClientScript.GetCallbackEventReference( this , i.ToString(), " AjaxPagerCallBack " , null ), i);
}
PageListStr.AppendFormat( " {0} " , PageInfo);
return PageListStr.ToString();
}
else
{
for ( int i = MinInt; i <= MaxInt; i ++ )
{
PageIndexColor = PageIndex == i ? " #CC0000 " : " #000000 " ;
if (PageIndex == i)
PageListStr.AppendFormat( " <a id={0}' style='color:{1};margin:auto 3px;'>{2}</a> " , this .UniqueID, PageIndexColor, i);
else
PageListStr.AppendFormat( " <a id='{0}' style='color:{1};margin:auto 3px;' href=\ " javascript:{ 2 }\ " >{3}</a> " , this .UniqueID, PageIndexColor, Page.ClientScript.GetCallbackEventReference( this , i.ToString(), " AjaxPagerCallBack " , null ), i);
}
if (PageIndex <= BarSize && TotalPage > BarSize)
{
PageListStr.AppendFormat( " <a id='{0}' href=\ " javascript:{ 1 }\ " >下一页</a> " , this .UniqueID, Page.ClientScript.GetCallbackEventReference( this , System.Convert.ToString(BarSize + 1 ), " AjaxPagerCallBack " , null ));
}
if ( this .PageIndex > BarSize && (TotalPage - this .PageIndex) >= SingleNumber)
{
int MultiMinPageIndex = (IntPageForMax * BarSize);
int MultiMaxPageIndex = ((IntPageForMax + 1 ) * BarSize) + 1 ;
PageListStr.Insert( 0 , string .Format( " <a id='{0}' href=\ " javascript:{ 1 }\ " >上一页</a> " , this .UniqueID, Page.ClientScript.GetCallbackEventReference( this , MultiMinPageIndex.ToString(), " AjaxPagerCallBack " , null )));
PageListStr.AppendFormat( " <a id='{0}' href=\ " javascript:{ 1 }\ " >下一页</a> " , this .UniqueID, Page.ClientScript.GetCallbackEventReference( this , MultiMaxPageIndex.ToString(), " AjaxPagerCallBack " , null ));
}
if (PageIndex > 10 && (TotalPage - PageIndex) < SingleNumber)
{
int MultiMinPageIndex = (IntPageForMax * BarSize);
PageListStr.Insert( 0 , string .Format( " <a id='{0}' href=\ " javascript:{ 1 }\ " >上一页</a> " , this .UniqueID, Page.ClientScript.GetCallbackEventReference( this , MultiMinPageIndex.ToString(), " AjaxPagerCallBack " , null )));
}
PageListStr.AppendFormat( " {0} " , PageInfo);
return PageListStr.ToString();
}
}
}
public void BindData()
{
Repeater rpt = getRpt();
rpt.Visible = true ;
SqlHelper helper;
helper = this .Info.ConnectStringName.IsNullOrEmpty() ? new SqlHelper() : new SqlHelper(Info.ConnectStringName);
if ( this .Info.RepeaterUniqueID.IsNullOrEmpty())
{
throw new Exception( " 必须给Info的RepeaterUniqueID属性赋值 " );
}
int count = 0 ;
DataTable dt = helper.GetPageData(Info.TableName, Info.Fields, Info.IdentityField, Info.PageSize, PageIndex, Info.IsDesc, Info.Content, out count);
this .TotalRecord = count;
rpt.DataShow(dt);
}
private Repeater getRpt()
{
return this .Page.FindControl( this .Info.RepeaterUniqueID) as Repeater;
}
先感谢一下写那个Pager的人,GetContents(得到自己分页后的HTML)里我只做了少许改动,要不然还得细细算来!!
BindData(用到了我的SqlHelper)是利用为服务器的DataBind()方法把数据放到repeater里,只是不让它呈示,嘿嘿!
getRpt只是找到Repeater引用
protected override void LoadViewState( object savedState)
{
Triplet tp = savedState as Triplet;
this .TotalRecord = Convert.ToInt32(tp.Third);
this .Info = tp.Second as PageInfo;
base .LoadViewState(tp.First);
}
protected override object SaveViewState()
{
Triplet tp = new Triplet();
tp.First = base .SaveViewState();
tp.Second = Info;
tp.Third = this .TotalRecord;
return tp;
}
#endregion
这里也不必说,只是PageInfo一定要能Serializable。
protected override void RenderContents(HtmlTextWriter writer)
{
writer.Write(GetContents());
base .RenderContents(writer);
}
protected override void AddAttributesToRender(HtmlTextWriter writer)
{
writer.AddStyleAttribute( " White-space " , " nowrap " );
writer.AddStyleAttribute( " padding-top " , " 2px " );
writer.AddStyleAttribute( " padding-bottom " , " 2px " );
writer.AddStyleAttribute( " color " , " #949494 " );
writer.AddStyleAttribute( " font-weight " , " bold " );
writer.AddStyleAttribute( " background-color " , this .BarBackGroundColor);
base .AddAttributesToRender(writer);
}
#endregion
也不用说,大家一看都明白。
public string GetCallbackResult()
{
StringBuilder sb = new StringBuilder ();
StringWriter sw = new StringWriter (sb);
getRpt().RenderControl( new HtmlTextWriter(sw));
return this .GetContents() + " [_] " + sb.ToString();
}
public void RaiseCallbackEvent( string eventArgument)
{
int pageindex = int .Parse(eventArgument);
this ._CurrentIndex = pageindex;
BindData();
}
#endregion
回调时先执行RaiseCallbackEvent,所以CurrentIndex改变了, BindData()执行了!!!!
返回时时执行GetCallbackResult,string用"[_]"分开,对应上面注册的AjaxPagerCallBack js方法中的var parts =returnData.split('[_]');
OK!简单的Ajax分页就这样简单的完成了!!!
Northwind Orders表调用如下:
页面中Repeater包含在<div id="AjaxData"></div>中
{
SinoHelper.PageInfo info = new SinoHelper.PageInfo();
info.PageSize = 5 ;
info.RepeaterUniqueID = rpt.UniqueID;
info.TableName = " Orders " ;
info.Fields = " OrderID,CustomerID,ShipCity " ;
info.IdentityField = " OrderID " ;
info.Content = content;
AjaxPager1.Info = info;
AjaxPager1.BindData();
}
附下载: