前段时间的项目中需要使用到分页控件,在网上找了不少,最终还是自己动手写一个,比较简单,后续功能以后再实现,现把代码及思路写下来,望大家批评指正。分页控件的分页形式大多分三种,一种是用URL传值,通过给页面指定QueryString传值当前页的索引;另一种类似于GridView里面的分页方式,通过改变内部的PageIndex分页;还有一种是两种方式都包含,那样功能比较强大,在此不做评论。用URL传值的方式,相当于每点击分页按钮,页面就跳转至一个新的页面,那么页面IsPostBack值每次都是False,如果页面上不需要输入查询条件,那当然是没有问题的,如果查询页面上面要输入一些查询条件,自然用URL传值就不太适用了,至少你得把你输入的查询条件传递到新的URL中。故此,我在做这个控件时用到了用PageIndex传值的方式。首先我用了一个分页的存储过程,代码如下:
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
Code
1
create procedure sp_PageList
2
@sqlstr nvarchar(4000), --查询字符串
3
@currentpage int, --第N页
4
@pagesize int --每页行数
5![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
6
as
7
set nocount on
8
declare @P1 int, --P1是游标的id
9
@rowcount int
10
exec sp_cursoropen @P1 output,@sqlstr,@scrollopt=1,@ccopt=1,@rowcount=@rowcount output
11
set @currentpage=(@currentpage-1)*@pagesize+1
12
exec sp_cursorfetch @P1,16,@currentpage,@pagesize
13
exec sp_cursorclose @P1
14
select @rowcount
15
set nocount off
16![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
17
GO
18![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
这个存储过程的执行结果包括三个表,第一个为空表,第二个是查询的结果集,显示的行数为@pagesize设置的大小,第三个是总记录数
下面是分页控件的代码:
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
Code
1
using System;
2
using System.ComponentModel;
3
using System.Text;
4
using System.Web;
5
using System.Web.UI;
6
using System.Web.UI.WebControls;
7![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
8
namespace WebControlEx
9![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
{
10
[ToolboxData("<{0}:Pager runat=\"server\" ></{0}:Pager>")]
11
public class Pager : CompositeControl, INamingContainer
12![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
13![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
公共属性#region 公共属性
14![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
15
[Browsable(true), Category("分页"), DefaultValue("0"), Localizable(true), Description("当前页的索引")]
16
public int PageIndex
17![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
18
get
19![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
20
return ViewState["PageIndex"] == null ? 0 : (int)ViewState["PageIndex"];
21
}
22![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
23
set
24![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
25
ViewState["PageIndex"] = value;
26
}
27
}
28![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
29
[Browsable(true), Category("分页"), DefaultValue("10"), Localizable(true), Description("数据源中每页要显示的行的数目")]
30
public int PageSize
31![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
32
get
33![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
34
return ViewState["PageSize"] == null ? 10 : (int)ViewState["PageSize"];
35
}
36![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
37
set
38![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
39
ViewState["PageSize"] = value;
40
}
41
}
42![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
43
[Browsable(true), Category("分页"), PersistenceMode(PersistenceMode.InnerProperty), Description("控制与控件关联的分页UI设置"), DesignerSerializationVisibility(DesignerSerializationVisibility.Content), NotifyParentProperty(true)]
44
public virtual PagerSettings PagerSettings
45![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
46
get
47![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
48
if (this._pagerSettings == null)
49![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
50
this._pagerSettings = new PagerSettings();
51
}
52
return this._pagerSettings;
53
}
54
}
55![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
56
[Browsable(true), Category("数据"), DefaultValue("0"), Localizable(true), Description("数据源的总行数")]
57
public int RecordCount
58![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
59
get
60![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
61
return ViewState["RecordCount"] == null ? 0 : (int)ViewState["RecordCount"];
62
}
63![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
64
set
65![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
66
ViewState["RecordCount"] = value;
67
}
68
}
69![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
70
#endregion
71![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
72![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
私有属性#region 私有属性
73![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
74
private int PageCount
75![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
76
get
77![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
78
if (this.RecordCount == 0 || this.PageSize == 0)
79
return 0;
80
return (int)Math.Ceiling(this.RecordCount / (this.PageSize * 1.0));
81
}
82
}
83![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
84
#endregion
85![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
86![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
私有变量#region 私有变量
87![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
88
private static readonly object EventPageIndexChanged = new object();
89
private PagerSettings _pagerSettings = new PagerSettings();
90![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
91
private LinkButton _lbtnFirst = new LinkButton();
92
private LinkButton _lbtnPrev = new LinkButton();
93
private LinkButton _lbtnNext = new LinkButton();
94
private LinkButton _lbtnLast = new LinkButton();
95![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
96
private TextBox txtPageIndex = new TextBox();
97![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
98
#endregion
99![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
100![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
事件相关#region 事件相关
101![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
102
[Description("Pager_OnPageIndexChanged"), Category("Action")]
103
public event EventHandler PageIndexChanged
104![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
105
add
106![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
107
base.Events.AddHandler(EventPageIndexChanged, value);
108
}
109
remove
110![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
111
base.Events.RemoveHandler(EventPageIndexChanged, value);
112
}
113
}
114![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
115
protected void OnPageChanged(EventArgs e)
116![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
117
EventHandler handler = (EventHandler)Events[EventPageIndexChanged];
118
if (handler != null)
119![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
120
handler(this, e);
121
}
122
}
123![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
124
#endregion
125![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
126![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
重写基类方法#region 重写基类方法
127![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
128
protected override void CreateChildControls()
129![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
130
this.Controls.Clear();
131![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
132
this._lbtnFirst.Text = this._pagerSettings.FirstPageText;
133
this._lbtnFirst.CommandName = "First";
134
this._lbtnFirst.Click += new EventHandler(LinkButtion_Click);
135![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
136
this._lbtnPrev.Text = this._pagerSettings.PreviousPageText;
137
this._lbtnPrev.CommandName = "Prev";
138
this._lbtnPrev.Click += new EventHandler(LinkButtion_Click);
139![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
140
this._lbtnNext.Text = this._pagerSettings.NextPageText;
141
this._lbtnNext.CommandName = "Next";
142
this._lbtnNext.Click += new EventHandler(LinkButtion_Click);
143![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
144
this._lbtnLast.Text = this._pagerSettings.LastPageText;
145
this._lbtnLast.CommandName = "Last";
146
this._lbtnLast.Click += new EventHandler(LinkButtion_Click);
147![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
148
txtPageIndex.Width = 30;
149
txtPageIndex.AutoPostBack = true;
150
txtPageIndex.TextChanged += new EventHandler(PageIndex_TextChanged);
151![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
152
this.Controls.Add(this._lbtnFirst);
153
this.Controls.Add(this._lbtnPrev);
154
this.Controls.Add(this._lbtnNext);
155
this.Controls.Add(this._lbtnLast);
156
this.Controls.Add(txtPageIndex);
157![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
158
base.CreateChildControls();
159
}
160![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
161
protected override void Render(HtmlTextWriter writer)
162![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
163
if (this.PageCount == 1)
164
return;
165
if (this.CssClass != "")
166![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
writer.Write("<div class=\"
{0}\">", this.CssClass);
167
else
168
writer.Write("<div>");
169
if (this.RecordCount == 0)
170![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
171
writer.Write("对不起,没有查询到相关记录!</div>");
172
return;
173
}
174
writer.Write("<table><tr><td>总记录:<span>{0}</span>条,每页<span>{1}</span>条,当前页:<span>{2}</span>/<span>{3}</span></td>", this.RecordCount, this.PageSize, this.PageIndex + 1, this.PageCount);
175![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
176![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
显示首页,上一页#region 显示首页,上一页
177![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
178
writer.Write("<td>");
179
if (this.PageIndex == 0 || this.PageCount == 1)
180![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
181
_lbtnFirst.Visible = false;
182
_lbtnPrev.Visible = false;
183
}
184
_lbtnFirst.RenderControl(writer);
185
writer.Write("</td><td>");
186
_lbtnPrev.RenderControl(writer);
187
writer.Write("</td>");
188![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
189
#endregion
190![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
191![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
显示下一页,末页#region 显示下一页,末页
192![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
193
writer.Write("<td>");
194
if (this.PageIndex == this.PageCount - 1 || this.PageCount == 1)
195![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
196
_lbtnNext.Visible = false;
197
_lbtnLast.Visible = false;
198
}
199
_lbtnNext.RenderControl(writer);
200
writer.Write("</td><td>");
201
_lbtnLast.RenderControl(writer);
202
writer.Write("</td>");
203![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
204
#endregion
205![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
206![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
跳转至#region 跳转至
207![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
208
writer.Write("<td>跳转至:</td><td style=\"width:45px\">");
209
txtPageIndex.RenderControl(writer);
210
writer.Write("</td></table></div>");
211![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
212
#endregion
213
}
214
215
#endregion
216![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
217![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
子控件的方法#region 子控件的方法
218![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
219
private void LinkButtion_Click(object sender, EventArgs e)
220![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
221
string commandName = (sender as LinkButton).CommandName;
222
switch (commandName)
223![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
224
case "First": this.PageIndex = 0; break;
225
case "Prev": this.PageIndex--; break;
226
case "Next": this.PageIndex++; break;
227
case "Last": this.PageIndex = this.PageCount - 1; break;
228
}
229
OnPageChanged(e);
230
}
231![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
232
private void PageIndex_TextChanged(object sender, EventArgs e)
233![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
234
if (txtPageIndex.Text.Trim().Length == 0)
235
return;
236
int pageIndex = 0;
237
if (int.TryParse(txtPageIndex.Text, out pageIndex))
238![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
239
if (pageIndex < 1)
240
this.PageIndex = 0;
241
else if (pageIndex > this.PageCount)
242
this.PageIndex = this.PageCount - 1;
243
else
244
this.PageIndex = pageIndex - 1;
245
}
246
OnPageChanged(e);
247
}
248![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
249
#endregion
250
}
251
}
252![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
代码不用多解释,当页数为1时,无任何输出,记录为零时,显示无相关记录的提示,其它情况下输出一个Div 和一个Table,Div是为了样式控制方便而输出的。
下面是用C#代码调用上面分页存储过程的示例
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
Code
/// <summary>
/// 数据分页
/// </summary>
/// <param name="cmdText">Sql语句</param>
/// <param name="curPage">当前为第几页</param>
/// <param name="pageSize">每页行数</param>
/// <param name="pageCount">返回的总页数</param>
/// <param name="rowCount">返回的总记录数</param>
/// <returns>返回数据表</returns>
private DataTable PagerList(string cmdText, int curPage, int pageSize, out int rowCount)
{
SqlConnection con = new SqlConnection("server=.;database=dbname;user id=user;password=password");
DataSet ds = new DataSet();
SqlDataAdapter da = new SqlDataAdapter("sp_PageList", con);
da.SelectCommand.CommandType = CommandType.StoredProcedure;
SqlParameter[] paras = new SqlParameter[]
{
new SqlParameter("@sqlstr",SqlDbType.NVarChar,4000),
new SqlParameter("@currentpage",SqlDbType.Int),
new SqlParameter("@pagesize",SqlDbType.Int)
};
paras[0].Value = cmdText;
paras[1].Value = curPage;
paras[2].Value = pageSize;
foreach (SqlParameter para in paras)
{
da.SelectCommand.Parameters.Add(para);
}
try
{
con.Open();
da.Fill(ds);
con.Close();
}
catch(Exception ex)
{
throw new Exception(ex.Message);
}
rowCount = Convert.ToInt32(ds.Tables[2].Rows[0][0]);
return ds.Tables[1];
}
public DataTable GetLog(int curPage, int pageSize, out int rowCount)
{
return this.PagerList("select *from tb_Log",curPage,pageSize,out rowCount);
}
之后便是将控件拖到页面上,设置PageSize值 绑定数据表到数据控件上
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
Code
public void BindGrid()
{
int recordCount =0;
GridView1.DataSource = this.GetLog(Pager1.PageIndex + 1, Pager1.PageSize,out recordCount);
GridView1.DataBind();
Pager1.RecordCount = recordCount;
}
/// <summary>
/// 分页控件的分页事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void Pager1_PageIndexChanged(object sender, EventArgs e)
{
this.BindGrid();
}
至此,该控件从编码到测试就完成了,测试的代码需要大家根据实际环境去调正一下才能运行,总结一下,这个分页控件对数据源、数据绑定控件都不关心,它要做的是传递给数据源当前页的索引值,分页大小,然后接受数据源传递过来的总记录数,至于数据绑定控件,GridView,DataList,Repeater都可以使用这个分页控件。