适用于ASP.NET的自定义分页控件

前段时间的项目中需要使用到分页控件,在网上找了不少,最终还是自己动手写一个,比较简单,后续功能以后再实现,现把代码及思路写下来,望大家批评指正。分页控件的分页形式大多分三种,一种是用URL传值,通过给页面指定QueryString传值当前页的索引;另一种类似于GridView里面的分页方式,通过改变内部的PageIndex分页;还有一种是两种方式都包含,那样功能比较强大,在此不做评论。用URL传值的方式,相当于每点击分页按钮,页面就跳转至一个新的页面,那么页面IsPostBack值每次都是False,如果页面上不需要输入查询条件,那当然是没有问题的,如果查询页面上面要输入一些查询条件,自然用URL传值就不太适用了,至少你得把你输入的查询条件传递到新的URL中。故此,我在做这个控件时用到了用PageIndex传值的方式。首先我用了一个分页的存储过程,代码如下:

ContractedBlock.gif ExpandedBlockStart.gif Code
 1create  procedure sp_PageList
 2@sqlstr nvarchar(4000), --查询字符串
 3@currentpage int--第N页
 4@pagesize int --每页行数
 5
 6as
 7set nocount on
 8declare @P1 int--P1是游标的id
 9 @rowcount int
10exec sp_cursoropen @P1 output,@sqlstr,@scrollopt=1,@ccopt=1,@rowcount=@rowcount output
11set @currentpage=(@currentpage-1)*@pagesize+1
12exec sp_cursorfetch @P1,16,@currentpage,@pagesize 
13exec sp_cursorclose @P1
14select @rowcount
15set nocount off
16
17GO
18

这个存储过程的执行结果包括三个表,第一个为空表,第二个是查询的结果集,显示的行数为@pagesize设置的大小,第三个是总记录数

下面是分页控件的代码:

 

ContractedBlock.gif ExpandedBlockStart.gif Code
  1using System;
  2using System.ComponentModel;
  3using System.Text;
  4using System.Web;
  5using System.Web.UI;
  6using System.Web.UI.WebControls;
  7
  8namespace WebControlEx
  9ExpandedBlockStart.gifContractedBlock.gif{
 10    [ToolboxData("<{0}:Pager runat=\"server\" >")]
 11    public class Pager : CompositeControl, INamingContainer
 12ExpandedSubBlockStart.gifContractedSubBlock.gif    {
 13ContractedSubBlock.gifExpandedSubBlockStart.gif        公共属性#region 公共属性
 14
 15        [Browsable(true), Category("分页"), DefaultValue("0"), Localizable(true), Description("当前页的索引")]
 16        public int PageIndex
 17ExpandedSubBlockStart.gifContractedSubBlock.gif        {
 18            get
 19ExpandedSubBlockStart.gifContractedSubBlock.gif            {
 20                return ViewState["PageIndex"== null ? 0 : (int)ViewState["PageIndex"];
 21            }

 22
 23            set
 24ExpandedSubBlockStart.gifContractedSubBlock.gif            {
 25                ViewState["PageIndex"= value;
 26            }

 27        }

 28
 29        [Browsable(true), Category("分页"), DefaultValue("10"), Localizable(true), Description("数据源中每页要显示的行的数目")]
 30        public int PageSize
 31ExpandedSubBlockStart.gifContractedSubBlock.gif        {
 32            get
 33ExpandedSubBlockStart.gifContractedSubBlock.gif            {
 34                return ViewState["PageSize"== null ? 10 : (int)ViewState["PageSize"];
 35            }

 36
 37            set
 38ExpandedSubBlockStart.gifContractedSubBlock.gif            {
 39                ViewState["PageSize"= value;
 40            }

 41        }

 42
 43        [Browsable(true), Category("分页"), PersistenceMode(PersistenceMode.InnerProperty), Description("控制与控件关联的分页UI设置"), DesignerSerializationVisibility(DesignerSerializationVisibility.Content), NotifyParentProperty(true)]
 44        public virtual PagerSettings PagerSettings
 45ExpandedSubBlockStart.gifContractedSubBlock.gif        {
 46            get
 47ExpandedSubBlockStart.gifContractedSubBlock.gif            {
 48                if (this._pagerSettings == null)
 49ExpandedSubBlockStart.gifContractedSubBlock.gif                {
 50                    this._pagerSettings = new PagerSettings();
 51                }

 52                return this._pagerSettings;
 53            }

 54        }

 55
 56        [Browsable(true), Category("数据"), DefaultValue("0"), Localizable(true), Description("数据源的总行数")]
 57        public int RecordCount
 58ExpandedSubBlockStart.gifContractedSubBlock.gif        {
 59            get
 60ExpandedSubBlockStart.gifContractedSubBlock.gif            {
 61                return ViewState["RecordCount"== null ? 0 : (int)ViewState["RecordCount"];
 62            }

 63
 64            set
 65ExpandedSubBlockStart.gifContractedSubBlock.gif            {
 66                ViewState["RecordCount"= value;
 67            }

 68        }

 69
 70        #endregion

 71
 72ContractedSubBlock.gifExpandedSubBlockStart.gif        私有属性#region 私有属性
 73
 74        private int PageCount
 75ExpandedSubBlockStart.gifContractedSubBlock.gif        {
 76            get
 77ExpandedSubBlockStart.gifContractedSubBlock.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
 84        #endregion

 85
 86ContractedSubBlock.gifExpandedSubBlockStart.gif        私有变量#region 私有变量
 87
 88        private static readonly object EventPageIndexChanged = new object();
 89        private PagerSettings _pagerSettings = new PagerSettings();
 90
 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
 96        private TextBox txtPageIndex = new TextBox();
 97
 98        #endregion

 99
100ContractedSubBlock.gifExpandedSubBlockStart.gif        事件相关#region 事件相关
101
102        [Description("Pager_OnPageIndexChanged"), Category("Action")]
103        public event EventHandler PageIndexChanged
104ExpandedSubBlockStart.gifContractedSubBlock.gif        {
105            add
106ExpandedSubBlockStart.gifContractedSubBlock.gif            {
107                base.Events.AddHandler(EventPageIndexChanged, value);
108            }

109            remove
110ExpandedSubBlockStart.gifContractedSubBlock.gif            {
111                base.Events.RemoveHandler(EventPageIndexChanged, value);
112            }

113        }

114
115        protected void OnPageChanged(EventArgs e)
116ExpandedSubBlockStart.gifContractedSubBlock.gif        {
117            EventHandler handler = (EventHandler)Events[EventPageIndexChanged];
118            if (handler != null)
119ExpandedSubBlockStart.gifContractedSubBlock.gif            {
120                handler(this, e);
121            }

122        }

123
124        #endregion

125
126ContractedSubBlock.gifExpandedSubBlockStart.gif        重写基类方法#region 重写基类方法
127
128        protected override void CreateChildControls()
129ExpandedSubBlockStart.gifContractedSubBlock.gif        {
130            this.Controls.Clear();
131
132            this._lbtnFirst.Text = this._pagerSettings.FirstPageText;
133            this._lbtnFirst.CommandName = "First";
134            this._lbtnFirst.Click += new EventHandler(LinkButtion_Click);
135
136            this._lbtnPrev.Text = this._pagerSettings.PreviousPageText;
137            this._lbtnPrev.CommandName = "Prev";
138            this._lbtnPrev.Click += new EventHandler(LinkButtion_Click);
139
140            this._lbtnNext.Text = this._pagerSettings.NextPageText;
141            this._lbtnNext.CommandName = "Next";
142            this._lbtnNext.Click += new EventHandler(LinkButtion_Click);
143
144            this._lbtnLast.Text = this._pagerSettings.LastPageText;
145            this._lbtnLast.CommandName = "Last";
146            this._lbtnLast.Click += new EventHandler(LinkButtion_Click);
147
148            txtPageIndex.Width = 30;
149            txtPageIndex.AutoPostBack = true;
150            txtPageIndex.TextChanged += new EventHandler(PageIndex_TextChanged);
151
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
158            base.CreateChildControls();
159        }

160
161        protected override void Render(HtmlTextWriter writer)
162ExpandedSubBlockStart.gifContractedSubBlock.gif        {
163            if (this.PageCount == 1)
164                return;
165            if (this.CssClass != "")
166ExpandedSubBlockStart.gifContractedSubBlock.gif                writer.Write(""{ 0}\">"this.CssClass);
167            else
168                writer.Write("
");
169            if (this.RecordCount == 0)
170ExpandedSubBlockStart.gifContractedSubBlock.gif            {
171                writer.Write("对不起,没有查询到相关记录!
");
172                return;
173            }

174            writer.Write(""this.RecordCount, this.PageSize, this.PageIndex + 1this.PageCount);
175
176ContractedSubBlock.gifExpandedSubBlockStart.gif            显示首页,上一页#region 显示首页,上一页
177
178            writer.Write("
");
188
189            #endregion
190
191ContractedSubBlock.gifExpandedSubBlockStart.gif            显示下一页,末页#region  显示下一页,末页
192
193            writer.Write("
");
203
204            #endregion
205
206ContractedSubBlock.gifExpandedSubBlockStart.gif            跳转至#region 跳转至
207
208            writer.Write("
"width:45px\">");
209            txtPageIndex.RenderControl(writer);
210            writer.Write("
总记录:{0}条,每页{1}条,当前页:{2}/{3}");
179            if (this.PageIndex == 0 || this.PageCount == 1)
180ExpandedSubBlockStart.gifContractedSubBlock.gif            {
181                _lbtnFirst.Visible = false;
182                _lbtnPrev.Visible = false;
183            }

184            _lbtnFirst.RenderControl(writer);
185            writer.Write("
");
186            _lbtnPrev.RenderControl(writer);
187            writer.Write("
");
194            if (this.PageIndex == this.PageCount - 1 || this.PageCount == 1)
195ExpandedSubBlockStart.gifContractedSubBlock.gif            {
196                _lbtnNext.Visible = false;
197                _lbtnLast.Visible = false;
198            }

199            _lbtnNext.RenderControl(writer);
200            writer.Write("
");
201            _lbtnLast.RenderControl(writer);
202            writer.Write("
跳转至:
");
211
212            #endregion
213        }
214 
215        #endregion
216
217ContractedSubBlock.gifExpandedSubBlockStart.gif        子控件的方法#region 子控件的方法
218
219        private void LinkButtion_Click(object sender, EventArgs e)
220ExpandedSubBlockStart.gifContractedSubBlock.gif        {
221            string commandName = (sender as LinkButton).CommandName;
222            switch (commandName)
223ExpandedSubBlockStart.gifContractedSubBlock.gif            {
224                case "First"this.PageIndex = 0break;
225                case "Prev"this.PageIndex--break;
226                case "Next"this.PageIndex++break;
227                case "Last"this.PageIndex = this.PageCount - 1break;
228            }

229            OnPageChanged(e);
230        }

231
232        private void PageIndex_TextChanged(object sender, EventArgs e)
233ExpandedSubBlockStart.gifContractedSubBlock.gif        {
234            if (txtPageIndex.Text.Trim().Length == 0)
235                return;
236            int pageIndex = 0;
237            if (int.TryParse(txtPageIndex.Text, out pageIndex))
238ExpandedSubBlockStart.gifContractedSubBlock.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
249        #endregion
 
250    }
251}
252

 

代码不用多解释,当页数为1时,无任何输出,记录为零时,显示无相关记录的提示,其它情况下输出一个Div 和一个Table,Div是为了样式控制方便而输出的。

下面是用C#代码调用上面分页存储过程的示例

 

ContractedBlock.gif ExpandedBlockStart.gif Code
/// 
        
/// 数据分页
        
/// 

        
/// Sql语句
        
/// 当前为第几页
        
/// 每页行数
        
/// 返回的总页数
        
/// 返回的总记录数
        
/// 返回数据表
        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值 绑定数据表到数据控件上

 

ContractedBlock.gif ExpandedBlockStart.gif Code
public void BindGrid()
        {
            
int recordCount =0;
            GridView1.DataSource 
= this.GetLog(Pager1.PageIndex + 1, Pager1.PageSize,out recordCount);
            GridView1.DataBind();

            Pager1.RecordCount 
= recordCount;
        }
/// 
        
/// 分页控件的分页事件
        
/// 

        
/// 
        
/// 
protected void Pager1_PageIndexChanged(object sender, EventArgs e)
        {
            
this.BindGrid();
        }

 

至此,该控件从编码到测试就完成了,测试的代码需要大家根据实际环境去调正一下才能运行,总结一下,这个分页控件对数据源、数据绑定控件都不关心,它要做的是传递给数据源当前页的索引值,分页大小,然后接受数据源传递过来的总记录数,至于数据绑定控件,GridView,DataList,Repeater都可以使用这个分页控件。

转载于:https://www.cnblogs.com/easyit/archive/2009/05/07/1451372.html

你可能感兴趣的:(ui,c#,数据库)