前言:
分页,大伙并不陌生
也许你正用着:DataGrid/GridView自带的分页
也许你正用着:网上流传较广的AspnetPager分页控件
也许你正用着:其它同事写的分页控件
又也许:你正是那个写分页控件的人,如果是,现在的你是否回头看过自己当初的源码?感觉?
也许你正用着:DataGrid/GridView自带的分页
也许你正用着:网上流传较广的AspnetPager分页控件
也许你正用着:其它同事写的分页控件
又也许:你正是那个写分页控件的人,如果是,现在的你是否回头看过自己当初的源码?感觉?
附言:
昨夜,花了两个小时左右,把一个2007年那会写的分页控件,重新优化改造了一下:
cs代码大小从原来的14K,缩减到4K。
原来的分页控件源码:点击下载
cs代码大小从原来的14K,缩减到4K。
原来的分页控件源码:点击下载
在看以下正文之前,还是希望能看一下原来的分页控件的源码,这样才能感叹下改造前后的巨大落差。
正文:
一:概述
目前分页控件,据个人所知的,有几下几种实现情况:
1:Post篇 [生成N个按钮,每个按钮点击时产生一个Post事件引发分页]
常见方式:控件实现复杂,内渗杂sql语句。
本文方式:反射机制,与sql无关。
遥想当年是配合了atlas的updatepanel实现的无刷新
本文方式:反射机制,与sql无关。
遥想当年是配合了atlas的updatepanel实现的无刷新
2:Get篇 [生成N个链接,每个链接点击时产生一个Get事件引发分页]
方式一:链接分页,常见于参数后面的page=N
方式二:链接分页,Url重写,常见于url参数为 /page/N
方式三:脚本分页,无刷新,链接都采用onclick="js函数"引发ajax回调异步分页。
方式二:链接分页,Url重写,常见于url参数为 /page/N
方式三:脚本分页,无刷新,链接都采用onclick="js函数"引发ajax回调异步分页。
二:实现
在具体写实现代码之前,我们上几张图片看一下效果:
说明:
昨夜把代码上传到网络空间时,忘了把样式也传上去,早上下载后发现没样式。
所以样式是自己临时加上去的,大伙自己感知一下效果了就可以了。
所以样式是自己临时加上去的,大伙自己感知一下效果了就可以了。
下面开始分页控件实现具体步骤:
1:新建一个用户控件:Pager
2:控件前台html
<
table
id
="pager"
border
="0"
cellpadding
="0"
cellspacing
="0"
width
="100%"
>
< tr >
< td >
< asp:LinkButton ID ="lbtnFirstLink" runat ="server" CausesValidation ="false" OnClick ="ClickEvent" > 首页 </ asp:LinkButton >
< asp:LinkButton ID ="lbtnPrevPage" runat ="server" CausesValidation ="false" OnClick ="ClickEvent" > 上一页 </ asp:LinkButton >
< asp:Repeater ID ="rptNum" runat ="server" OnItemCommand ="rptNum_ItemCommand" >
< ItemTemplate >
< asp:LinkButton ID ="lbtnNum" runat ="server" CausesValidation ="false" CommandArgument ='<%# Container.DataItem % > '
CssClass=' <% # Convert.ToInt32(Container.DataItem) == PageIndex? " num_yellow " : " num_blue " %> ' Width="15"> <% # Container.DataItem %>
< tr >
< td >
< asp:LinkButton ID ="lbtnFirstLink" runat ="server" CausesValidation ="false" OnClick ="ClickEvent" > 首页 </ asp:LinkButton >
< asp:LinkButton ID ="lbtnPrevPage" runat ="server" CausesValidation ="false" OnClick ="ClickEvent" > 上一页 </ asp:LinkButton >
< asp:Repeater ID ="rptNum" runat ="server" OnItemCommand ="rptNum_ItemCommand" >
< ItemTemplate >
< asp:LinkButton ID ="lbtnNum" runat ="server" CausesValidation ="false" CommandArgument ='<%# Container.DataItem % > '
CssClass=' <% # Convert.ToInt32(Container.DataItem) == PageIndex? " num_yellow " : " num_blue " %> ' Width="15"> <% # Container.DataItem %>
</
asp:LinkButton
>
</ ItemTemplate >
</ asp:Repeater >
< asp:LinkButton ID ="lbtnNextPage" runat ="server" CausesValidation ="false" OnClick ="ClickEvent" > 下一页 </ asp:LinkButton >
< asp:LinkButton ID ="lbtnLastPage" runat ="server" CausesValidation ="false" OnClick ="ClickEvent" > 尾页 </ asp:LinkButton >
< asp:HiddenField ID ="hfBindName" runat ="server" />
</ td >
</ tr >
</ table >
</ ItemTemplate >
</ asp:Repeater >
< asp:LinkButton ID ="lbtnNextPage" runat ="server" CausesValidation ="false" OnClick ="ClickEvent" > 下一页 </ asp:LinkButton >
< asp:LinkButton ID ="lbtnLastPage" runat ="server" CausesValidation ="false" OnClick ="ClickEvent" > 尾页 </ asp:LinkButton >
< asp:HiddenField ID ="hfBindName" runat ="server" />
</ td >
</ tr >
</ table >
说明:
A:用了表格布局,简单,想换div的自己改了。
B:用了五个LinkButton,其中数字的一个用Repeater循环N个数字出来
C:最后加了一个隐藏域,用于保存绑定的方法名称。
B:用了五个LinkButton,其中数字的一个用Repeater循环N个数字出来
C:最后加了一个隐藏域,用于保存绑定的方法名称。
D:数字里有两个样式用于为数字赋样式,样式到示例时再写出来吧
E:首页/上一页/下一页/尾页,用的点击事件都是同一个函数。
F:Repeater有个OnItemCommand事件,点击数字要重新绑定的。
3:后台cs代码
A:几个属性
private
int
_PageIndex;
public int PageIndex
{
get { if (_PageIndex == 0 ){ _PageIndex = 1 ;} return _PageIndex;}
set { _PageIndex = value;}
}
private int _PageSize;
public int PageSize
{
get { if (_PageSize == 0 ){_PageSize = 1 ;} return _PageSize;}
set { _PageSize = value;}
}
private int _Count;
public int Count
{
get { return _Count; }
set { _Count = value; }
}
/// <summary>
/// 该方法名称修饰符为需为public
/// </summary>
public string BindName
{
get { return hfBindName.Value;}
set {hfBindName.Value = value; }
}
public int PageIndex
{
get { if (_PageIndex == 0 ){ _PageIndex = 1 ;} return _PageIndex;}
set { _PageIndex = value;}
}
private int _PageSize;
public int PageSize
{
get { if (_PageSize == 0 ){_PageSize = 1 ;} return _PageSize;}
set { _PageSize = value;}
}
private int _Count;
public int Count
{
get { return _Count; }
set { _Count = value; }
}
/// <summary>
/// 该方法名称修饰符为需为public
/// </summary>
public string BindName
{
get { return hfBindName.Value;}
set {hfBindName.Value = value; }
}
说明:
PageIndex:第几页
PageSize:每页多少条
Count:记录总数
BindName:绑定的方法名称,用于反射绑定数据
PageSize:每页多少条
Count:记录总数
BindName:绑定的方法名称,用于反射绑定数据
B:Page_Load做点什么
private
void
Page_Load(
object
sender, System.EventArgs e)
{
if ( ! Page.IsPostBack)
{
BindPager(); // 绑定分页数字
}
}
{
if ( ! Page.IsPostBack)
{
BindPager(); // 绑定分页数字
}
}
说明:
第一次绑定时,界面已实现绑定数据,所以只需要绑定分页的数字就行了
C:绑定分页数字
public
void
BindPager()
{
int pageCount = (Count % PageSize) == 0 ? Count / PageSize : Count / PageSize + 1 ; // 页数
SetButtonEnable(pageCount); // 下面四个按钮可用状态设置
BindPageNum(pageCount); // 绑定循环数字
}
{
int pageCount = (Count % PageSize) == 0 ? Count / PageSize : Count / PageSize + 1 ; // 页数
SetButtonEnable(pageCount); // 下面四个按钮可用状态设置
BindPageNum(pageCount); // 绑定循环数字
}
说明:
1:从记录总数和页面大小计算出有多少页,这个少不的。
2:根据当页的页数和当前页面索引,设置下“首页/下一页/上一页/尾页”的可用状态
3:根据当前的页数绑定一下循环的数字。
2:根据当页的页数和当前页面索引,设置下“首页/下一页/上一页/尾页”的可用状态
3:根据当前的页数绑定一下循环的数字。
函数分解:SetButtonEnable [设置按钮可用状态及参数赋值]
private
void
SetButtonEnable(
int
pageCount)
{
lbtnFirstLink.Enabled = PageIndex != 1 ;
lbtnPrevPage.Enabled = PageIndex != 1 ;
lbtnNextPage.Enabled = PageIndex != pageCount;
lbtnLastPage.Enabled = PageIndex != pageCount;
lbtnFirstLink.CommandArgument = " 1 " ;
lbtnPrevPage.CommandArgument = (PageIndex - 1 ).ToString();
lbtnNextPage.CommandArgument = (PageIndex + 1 ).ToString();
lbtnLastPage.CommandArgument = pageCount.ToString();
}
{
lbtnFirstLink.Enabled = PageIndex != 1 ;
lbtnPrevPage.Enabled = PageIndex != 1 ;
lbtnNextPage.Enabled = PageIndex != pageCount;
lbtnLastPage.Enabled = PageIndex != pageCount;
lbtnFirstLink.CommandArgument = " 1 " ;
lbtnPrevPage.CommandArgument = (PageIndex - 1 ).ToString();
lbtnNextPage.CommandArgument = (PageIndex + 1 ).ToString();
lbtnLastPage.CommandArgument = pageCount.ToString();
}
说明:
1:如果当前页为第1页:首页/上一页状态不可用
2:如果当前页为最后1页:下一页/尾页状态不可用
3:顺路把几个页索引值赋给CommandArgument
2:如果当前页为最后1页:下一页/尾页状态不可用
3:顺路把几个页索引值赋给CommandArgument
函数分解:BindPageNum [绑定分页数字]
protected
void
BindPageNum(
int
pageCount)
{
int start = 1 , end = 10 ;
if (pageCount < end) // 页数小于10
{
end = pageCount;
}
else
{
start = (PageIndex > 5 ) ? PageIndex - 5 : start;
int result = (start + 9 ) - pageCount; // 是否超过最后面的页数
if (result > 0 )
{
end = pageCount;
start -= result; // 超过后,补差
}
else
{
end = start + 9 ;
}
}
ReBindNum(start, end);
}
{
int start = 1 , end = 10 ;
if (pageCount < end) // 页数小于10
{
end = pageCount;
}
else
{
start = (PageIndex > 5 ) ? PageIndex - 5 : start;
int result = (start + 9 ) - pageCount; // 是否超过最后面的页数
if (result > 0 )
{
end = pageCount;
start -= result; // 超过后,补差
}
else
{
end = start + 9 ;
}
}
ReBindNum(start, end);
}
说明:
1:由于绑定的数字,在往后页数点击时,页数数字需要进行变化,所以需计算好开始数字和结束数字
2:根据开始数字和结束数字进行绑定
2:根据开始数字和结束数字进行绑定
函数分解:ReBindNum [循环绑定数字]
private
void
ReBindNum(
int
start,
int
end)
{
int [] rows = new int [end-start+1 ];//这里之前写10,修正为end-start+1。
int index = 0 ;
for ( int i = start; i <= end; i ++ )
{
rows[index] = i;
index ++ ;
}
rptNum.DataSource = rows;
rptNum.DataBind();
}
{
int [] rows = new int [end-start+1 ];//这里之前写10,修正为end-start+1。
int index = 0 ;
for ( int i = start; i <= end; i ++ )
{
rows[index] = i;
index ++ ;
}
rptNum.DataSource = rows;
rptNum.DataBind();
}
说明:
1:这里用int[]数组循环数字来绑定到Repeater
2:界面绑定用 < %# Container.DataItem % > 方式进行对应
2:界面绑定用 < %# Container.DataItem % > 方式进行对应
D:反射绑定[简洁重点函数]
private void ReBindData(string pageIndex)
{
PageIndex = int.Parse(pageIndex);
object obj = base.Parent is HtmlForm ? this.Page : base.Parent;
MethodInfo mi = obj.GetType().GetMethod(BindName);
mi.Invoke(obj,null);
BindPager();
}
{
PageIndex = int.Parse(pageIndex);
object obj = base.Parent is HtmlForm ? this.Page : base.Parent;
MethodInfo mi = obj.GetType().GetMethod(BindName);
mi.Invoke(obj,null);
BindPager();
}
说明:
1:重点在于区分,分页控件是直接在页面中使用,还是在控件套分页控件的方式使用
2:获取绑定数据的方法,重新调用一下
3:重新绑定分布数字
2:获取绑定数据的方法,重新调用一下
3:重新绑定分布数字
F:首页/上一页/下一页/尾页,按钮事件
protected void ClickEvent(object sender, EventArgs e)
{
ReBindData(((LinkButton)sender).CommandArgument.ToString());
}
{
ReBindData(((LinkButton)sender).CommandArgument.ToString());
}
G:分页数字,按钮事件
protected void rptNum_ItemCommand(object source, RepeaterCommandEventArgs e)
{
ReBindData(e.CommandArgument.ToString());
}
{
ReBindData(e.CommandArgument.ToString());
}
三:示例代码,和 CYQ.Data轻量数据层框架 配合使用
1:html代码
<%
@ Page Language
=
"
C#
"
AutoEventWireup
=
"
true
"
CodeFile
=
"
PagerDemo.aspx.cs
"
Inherits
=
"
PagerDemo
"
EnableTheming
=
"
false
"
%>
<% @ Register Src = " UserControls/Pager.ascx " TagName = " Pager " TagPrefix = " uc1 " %>
<! DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" >
< html xmlns ="http://www.w3.org/1999/xhtml" >
< head runat ="server" >
< title > 路过秋天 分页控件演示 </ title >
< style type ="text/css" >
#pager { color : White ; }
#pager a { color : White ; text-decoration : none ; }
.num_blue { color : White ; border : solid 1px Blue ; text-align : center ; }
.num_yellow { color : while ; border : solid 1px Yellow ; text-align : center ; }
</ style >
</ head >
< body style ="background-color:Black;color:White;" >
< form id ="form1" runat ="server" >
< div >< asp:GridView ID ="gvUsers" runat ="server" ></ asp:GridView >< br />
< uc1:Pager ID ="Pager1" runat ="server" />
</ div >
</ form >
</ body >
</ html >
<% @ Register Src = " UserControls/Pager.ascx " TagName = " Pager " TagPrefix = " uc1 " %>
<! DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" >
< html xmlns ="http://www.w3.org/1999/xhtml" >
< head runat ="server" >
< title > 路过秋天 分页控件演示 </ title >
< style type ="text/css" >
#pager { color : White ; }
#pager a { color : White ; text-decoration : none ; }
.num_blue { color : White ; border : solid 1px Blue ; text-align : center ; }
.num_yellow { color : while ; border : solid 1px Yellow ; text-align : center ; }
</ style >
</ head >
< body style ="background-color:Black;color:White;" >
< form id ="form1" runat ="server" >
< div >< asp:GridView ID ="gvUsers" runat ="server" ></ asp:GridView >< br />
< uc1:Pager ID ="Pager1" runat ="server" />
</ div >
</ form >
</ body >
</ html >
2:后台代码
protected
void
Page_Load(
object
sender, EventArgs e)
{
if ( ! IsPostBack)
{
LoadData();
}
}
public void LoadData()
{
int count;
MAction action = new MAction(TableNames.Users);
MDataTable mTable = action.Select(Pager1.PageIndex, Pager1.PageSize, "" , out count);
action.Close();
gvUsers.DataSource = mTable;
gvUsers.DataBind();
Pager1.BindName = " LoadData " ;
Pager1.Count = count;
}
{
if ( ! IsPostBack)
{
LoadData();
}
}
public void LoadData()
{
int count;
MAction action = new MAction(TableNames.Users);
MDataTable mTable = action.Select(Pager1.PageIndex, Pager1.PageSize, "" , out count);
action.Close();
gvUsers.DataSource = mTable;
gvUsers.DataBind();
Pager1.BindName = " LoadData " ;
Pager1.Count = count;
}
说明:
1:BindName为绑定数据的方法名称,该方法名称的修饰符号需为public
2: 默认的分页PageSize可自行修改默认值
3: 前面html也可设置为: < uc1:Pager ID ="Pager1" runat ="server" PageSize ="20" />
2: 默认的分页PageSize可自行修改默认值
3: 前面html也可设置为: < uc1:Pager ID ="Pager1" runat ="server" PageSize ="20" />
3:最终效果
如正文一开始发的五张图片一致
结言:
以上教程中,以包含所有代码,包括前后台,所以不另提供打包下载。
有兴趣的来客欢迎讨论留言。
有兴趣的来客欢迎讨论留言。
源码下载地址:http://www.cyqdata.com/download/article-detail-28683
版权声明:本文原创发表于博客园,作者为路过秋天,原文链接:
http://www.cnblogs.com/cyq1162/archive/2010/08/30/1812361.html