自己动手开发服务器控件-------分页控件

对于一个大型业务系统来说,数据分页显示,是必不可少的。

但是怎么分、用什么分,方法和工具就有很多了。。。

刚入门的时候,总是会很习惯的从工具箱中拖出一个GridView,加上AllowPaging="true",再写个OnPageIndexChanging事件,OK,分页实现了。。。

发现这种方式效率差后,就开始拖.Net3.5中的独立分页控件了,忘了叫什么名字,公司用.Net2.0,没办法。

这些方式,基本上都是一次就查出所有数据,再分页。

------------------------------------------------------------------------------------------------------------------------------------------------

当然了,需要第几页就查第几页的数据,这才是最好的。 

所以,后来,也很傻的自己拖4个按钮(第一页、上一页、下一页、最后一页),一个下拉框(当前第N页),

然后为每个按钮写Click事件,为下拉框写Change事件,再配上分页存储过程,

嗯,是比之前几种方式要快一些。就是太繁琐,显然几乎没人会这么干。

 ------------------------------------------------------------------------------------------------------------------------------------------------

这会就有了做个简单的分页控件的想法,可是又不会,也没做过。

好吧,中关村买书去。。。

边看书边琢磨了两天,终于出来了。。。

不需要很强大,不需要很华丽,只要。。。够用就行。

 

加上CSS样式,最终显示效果就是这样,应该够用吧?反正我们是够了。。。哈哈


------------------------------------------------------------------------------------------------------------------------------------------------

首先,这是一个组合控件,5个按钮+1个输入框构成。

原理是让这5个按钮都调用同一个方法,同时再根据点击的按钮来判断页索引。

开始贴代码吧:

控件声明
 1 //设置控件在页面中的显示代码,如<Feli:Pager .....>
2 [assembly: TagPrefix("FeliControls", "Feli")]
3 namespace FeliControls
4 {
5 [DefaultProperty("ShowCountInfo")]//在VS属性栏中默认选中的属性
6 [DefaultEvent("PageIndexChanged")]//默认事件,设置后,双击控件就进入CS代码中该事件的声明,如Button控件的这个属性就是Click
7 [ToolboxData("<{0}:Pager runat=server></{0}:Pager>")]//在页面中调用时的显示代码
8 publicclass Pager : CompositeControl
9 {
10 //继承自CompositeControl,即组合控件
11 }
12 }


然后呢,就是各个子控件了。

子控件声明
1 private Button btnFirst;
2 private Button btnPrev;
3 private Button btnNext;
4 private Button btnLast;
5 private Button btnDiy;
6
7 private TextBox txtPageIndex;

接着呢,这些个按钮的文字,得允许自己设置吧。

子控件属性
  1         [Bindable(true)]
2 [Category("Appearance")]//在VS属性栏中所属的分组
3 [DefaultValue("")]
4 [Localizable(true)]
5 [Description("是否显示数据总数及当前显示数据信息")]//显示在VS属性栏下页的描述信息
6 publicbool ShowCountInfo
7 {
8 get
9 {
10 bool s =true;
11 if(!this.DesignMode)//非设计模式才取ViewState
12 {
13 if (ViewState["ShowCountInfo"] !=null)
14 {
15 s = (bool)ViewState["ShowCountInfo"];
16 }
17 }
18 return s;
19 }
20
21 set
22 {
23 ViewState["ShowCountInfo"] = value;
24 }
25 }
26 ///<summary>
27 /// 第一页按钮文字描述
28 ///</summary>
29 [Bindable(true)]
30 [Category("分页按钮属性")]
31 [DefaultValue("")]
32 [Localizable(true)]
33 [Description("第一页按钮文字")]
34 publicstring FirstPageText
35 {
36 get
37 {
38 EnsureChildControls();
39 return btnFirst.Text;
40 }
41
42 set
43 {
44 EnsureChildControls();
45 btnFirst.Text = value;
46 }
47 }
48 ///<summary>
49 /// 上一页按钮文字描述
50 ///</summary>
51 [Bindable(true)]
52 [Category("分页按钮属性")]
53 [DefaultValue("")]
54 [Localizable(true)]
55 [Description("上一页按钮文字")]
56 publicstring PrevPageText
57 {
58 get
59 {
60 EnsureChildControls();
61 return btnPrev.Text;
62 }
63
64 set
65 {
66 EnsureChildControls();
67 btnPrev.Text = value;
68 }
69 }
70 ///<summary>
71 /// 下一页按钮文字描述
72 ///</summary>
73 [Bindable(true)]
74 [Category("分页按钮属性")]
75 [DefaultValue("")]
76 [Localizable(true)]
77 [Description("下一页按钮文字")]
78 publicstring NextPageText
79 {
80 get
81 {
82 EnsureChildControls();
83 return btnNext.Text;
84 }
85
86 set
87 {
88 EnsureChildControls();
89 btnNext.Text = value;
90 }
91 }
92 ///<summary>
93 /// 最后一页按钮文字描述
94 ///</summary>
95 [Bindable(true)]
96 [Category("分页按钮属性")]
97 [DefaultValue("")]
98 [Localizable(true)]
99 [Description("最后一页按钮文字")]
100 publicstring LastPageText
101 {
102 get
103 {
104 EnsureChildControls();
105 return btnLast.Text;
106 }
107
108 set
109 {
110 EnsureChildControls();
111 btnLast.Text = value;
112 }
113 }
114
115 ///<summary>
116 /// GO按钮文字描述
117 ///</summary>
118 [Bindable(true)]
119 [Category("分页按钮属性")]
120 [DefaultValue("")]
121 [Localizable(true)]
122 [Description("自定义跳转到页面按钮文字")]
123 publicstring BtnGoText
124 {
125 get
126 {
127 EnsureChildControls();
128 return btnDiy.Text;
129 }
130
131 set
132 {
133 EnsureChildControls();
134 btnDiy.Text = value;
135 }
136 }

嗯,还有分页(第几页、数据总数、每页显示几条等)数量信息

分页属性相关
  1 publicint CurrentPageIndex
2 {
3 get
4 {
5 int idx =1;
6 if (!this.DesignMode)
7 {
8 if (txtPageIndex.Text !=null&& txtPageIndex.Text !="")
9 {
10 idx = Convert.ToInt32(txtPageIndex.Text.Trim());
11 }
12 }
13 return idx;
14 }
15 set
16 {
17 EnsureChildControls();//确认子控件已创建,未创建则会调用下面的CreateChildControls方法
18
19 if (value <2)
20 {
21 value =1;
22 }
23 if (value >=this.PageCount)
24 {
25 value =this.PageCount;
26 }
27 if (ViewState["CurrentPageIndex"] !=null)
28 {
29 string strPage = ViewState["CurrentPageIndex"].ToString();
30 }
31 txtPageIndex.Text = value.ToString();
32 }
33 }
34 ///<summary>
35 /// 总页数
36 ///</summary>
37 publicint PageCount
38 {
39 get
40 {
41 if (this.DesignMode)
42 {
43 return0;
44 }
45 else
46 {
47 return RecordCount % PageSize ==0? RecordCount / PageSize : (RecordCount / PageSize) +1;//直接计算共有多少页
48 }
49 }
50 }
51 ///<summary>
52 /// 每页显示的记录数
53 ///</summary>
54 [Bindable(true)]
55 [Category("分页信息")]
56 [DefaultValue("")]
57 [Localizable(true)]
58 [Description("每页显示的数据数")]
59 publicint PageSize
60 {
61 get
62 {
63 int _size =30;
64 if (!this.DesignMode)
65 {
66 if (ViewState["PageSize"] !=null)
67 {
68 _size = (int)ViewState["PageSize"];
69 }
70 }
71 return _size;
72 }
73 set
74 {
75 ViewState["PageSize"] = value;
76 }
77 }
78
79 ///<summary>
80 /// 总记录数
81 ///</summary>
82 [Bindable(true)]
83 [Category("分页信息")]
84 [DefaultValue("")]
85 [Localizable(true)]
86 [Description("总记录数")]
87 publicint RecordCount
88 {
89 get
90 {
91 int idx =0;
92 if (!this.DesignMode)
93 {
94 if (ViewState["RecordCount"] !=null)
95 {
96 idx = (int)ViewState["RecordCount"];
97 }
98 }
99 return idx;
100 }
101 set
102 {
103 ViewState["RecordCount"] = value;
104 }
105 }

因为自定义服务器控件,未重写HTML标签的话,好像都是<span>,所以就重写了下,用DIV

重写控件生成的HTML代码标签
 1 ///<summary>
2 /// 重写控件HTML代码开始标签
3 ///</summary>
4 protectedoverride HtmlTextWriterTag TagKey
5 {
6 get
7 {
8 return HtmlTextWriterTag.Div;
9 }
10 }

接下来创建子控件了

创建子控件
 1 protectedoverridevoid CreateChildControls()
2 {
3 this.Controls.Clear();//先清除现有的控件
4
5 btnFirst =new Button();
6 btnFirst.ID ="btnFirst";
7 btnFirst.CommandName ="Page";
8 btnFirst.CommandArgument ="ButtonFirst";
9 btnFirst.Click +=new EventHandler(Change_PageIndex);//绑上单击事件
10 btnFirst.Text ="第一页";
11 btnFirst.CssClass ="input_border felipager_btn_first";
12
13 this.Controls.Add(btnFirst);
14
15 btnPrev =new Button();
16 btnPrev.ID ="btnPrev";
17 btnPrev.CommandName ="Page";
18 btnPrev.CommandArgument ="ButtonPrev";
19 btnPrev.Click +=new EventHandler(Change_PageIndex);
20 btnPrev.Text ="上一页";
21 btnPrev.CssClass ="input_border mr20 felipager_btn_prev";
22
23 this.Controls.Add(btnPrev);
24
25 btnNext =new Button();
26 btnNext.ID ="btnNext";
27 btnNext.CommandName ="Page";
28 btnNext.CommandArgument ="ButtonNext";
29 btnNext.Click +=new EventHandler(Change_PageIndex);
30 btnNext.Text ="下一页";
31 btnNext.CssClass ="input_border ml20 felipager_btn_next";
32
33 this.Controls.Add(btnNext);
34
35 btnLast =new Button();
36 btnLast.ID ="btnLast";
37 btnLast.CommandName ="Page";
38 btnLast.CommandArgument ="ButtonLast";
39 btnLast.Click +=new EventHandler(Change_PageIndex);
40 btnLast.Text ="最后一页";
41 btnLast.CssClass ="input_border felipager_btn_last";
42
43 this.Controls.Add(btnLast);
44
45 btnDiy =new Button();
46 btnDiy.ID ="btnDiy";
47 btnDiy.CommandName ="Page";
48 btnDiy.CommandArgument ="ButtonDiy";
49 btnDiy.Click +=new EventHandler(Change_PageIndex);
50 btnDiy.Text ="GO";
51 btnDiy.CssClass ="input_border felipager_btn_go";
52
53 this.Controls.Add(btnDiy);
54
55 txtPageIndex =new TextBox();
56 txtPageIndex.ID ="txtPageIndex";
57 txtPageIndex.Width =30;
58 txtPageIndex.CssClass ="input_border felipager_txt_pageindex";
59
60 this.Controls.Add(txtPageIndex);
61
62 base.CreateChildControls();
63 }

可以看到,5个按钮都会触发同一事件。

各按钮单击事件
 1 void Change_PageIndex(object sender, EventArgs e)
2 {
3 //触发了点击事件,则将blnNoClick设为false.
4 blnNoClick =false;
5 Button btn = (Button)sender;
6 if (btn.CommandName =="Page")
7 {
8 PageChangedEventArgs ee =new PageChangedEventArgs();
9 if (btn.CommandArgument =="ButtonFirst")
10 {
11 this.CurrentPageIndex =1;
12 }
13 if (btn.CommandArgument =="ButtonPrev")
14 {
15 this.CurrentPageIndex -=1;
16 }
17 if (btn.CommandArgument =="ButtonNext")
18 {
19 this.CurrentPageIndex +=1;
20 }
21 if (btn.CommandArgument =="ButtonLast")
22 {
23 this.CurrentPageIndex =this.PageCount;
24 }
25 if (btn.CommandArgument =="ButtonDiy")
26 {
27 int intDiyIdx =1;
28 //如果输入数字不合法,则跳转到第一页
29 if (int.TryParse(this.txtPageIndex.Text, out intDiyIdx))
30 {
31 if (intDiyIdx >0)
32 {
33 this.CurrentPageIndex = intDiyIdx;
34 }
35 else
36 {
37 this.Page.RegisterStartupScript("tishi", "<script>alert('页索引必须为大于0的整数');</script>");
38 this.CurrentPageIndex =1;
39 }
40 }
41 else
42 {
43 this.Page.RegisterStartupScript("tishi", "<script>alert('页索引必须为整数');</script>");
44 this.CurrentPageIndex =1;
45 }
46 }
47 ee.CurrentPageIndex =this.CurrentPageIndex;
48 ee.PageCount =this.PageCount;
49 ee.PageSize =this.PageSize;
50 ee.RecordCount =this.RecordCount;
51 this.OnPageIndexChanged(ee);
52 }

最后就是渲染控件了

渲染控件
 1 protectedoverridevoid RenderContents(HtmlTextWriter output)
2 {
3 output.AddAttribute(HtmlTextWriterAttribute.Class, "felipager_displayinfo");
4 output.RenderBeginTag(HtmlTextWriterTag.Div);
5 //如果需要显示数据总数信息,则显示
6 if (this.ShowCountInfo)
7 {
8 int intStart =this.PageSize * (this.CurrentPageIndex -1);
9 if (intStart <1)
10 {
11 intStart =0;
12 }
13 int intEnd =this.PageSize *this.CurrentPageIndex;
14 if (intEnd >this.RecordCount)
15 {
16 intEnd =this.RecordCount;
17 }
18 intStart +=1;//每页的第一条的序号应该是1,而不是0
19 output.Write("共有 {0} 条数据,当前显示 {1} - {2} 条", this.RecordCount, intStart, intEnd);
20 }
21 output.RenderEndTag();
22
23 output.AddAttribute(HtmlTextWriterAttribute.Class, "felipager_navbox");
24 output.RenderBeginTag(HtmlTextWriterTag.Div);
25
26 #region ----控制导航按钮状态
27
28 //如果是第一页,则该按钮不可用
29 if (this.CurrentPageIndex ==1)
30 {
31 btnFirst.Enabled =false;
32 }
33 else
34 {
35 btnFirst.Enabled =true;
36 }
37 //如果是第一页,则该按钮不可用
38 if (this.CurrentPageIndex ==1)
39 {
40 btnPrev.Enabled =false;
41 }
42 else
43 {
44 btnPrev.Enabled =true;
45 }
46 //如果是最后一页,则该按钮不可用
47 if (this.CurrentPageIndex >=this.PageCount)
48 {
49 btnNext.Enabled =false;
50 }
51 else
52 {
53 btnNext.Enabled =true;
54 }
55 //如果是最后一页,则该按钮不可用
56 if (this.CurrentPageIndex >=this.PageCount)
57 {
58 btnLast.Enabled =false;
59 }
60 else
61 {
62 btnLast.Enabled =true;
63 }
64 //如果只有一页,则该按钮不可用
65 if (this.PageCount <=1)
66 {
67 btnDiy.Enabled =false;
68 }
69 else
70 {
71 btnDiy.Enabled =true;
72 }
73 //如果只有一页,则该输入框不可用
74 if (this.PageCount <=1)
75 {
76 txtPageIndex.Enabled =false;
77 }
78 else
79 {
80 txtPageIndex.Enabled =true;
81 }
82
83 #endregion
84
85 btnFirst.RenderControl(output);
86 btnPrev.RenderControl(output);
87 output.Write("当前第");
88 txtPageIndex.Text =this.CurrentPageIndex.ToString();
89 txtPageIndex.RenderControl(output);
90 btnDiy.RenderControl(output);
91 output.Write("页,共{0}页", this.PageCount);
92 btnNext.RenderControl(output);
93 btnLast.RenderControl(output);
94
95 output.RenderEndTag();
96 }

不过还缺了点东西,因为点击按钮时,分页控件需要将接下来要显示的页索引告诉分页方法,这样分页方法才知道需要去查询第几页的数据。

所以,我就写了这个。

分页控件事件参数
 1 ///<summary>
2 /// 分页控件事件参数类
3 ///</summary>
4 publicclass PageChangedEventArgs:System.EventArgs
5 {
6 public PageChangedEventArgs()
7 { }
8 ///<summary>
9 /// 当前页索引
10 ///</summary>
11 privateint intCurrentPageIndex;
12 publicnewint CurrentPageIndex
13 {
14 get { return intCurrentPageIndex; }
15 set { intCurrentPageIndex = value; }
16 }
17 ///<summary>
18 /// 数据总页数
19 ///</summary>
20 privateint intPageCount;
21 publicnewint PageCount
22 {
23 get { return intPageCount; }
24 set { intPageCount = value; }
25 }
26 ///<summary>
27 /// 每页显示的记录数
28 ///</summary>
29 privateint intPageSize;
30 publicnewint PageSize
31 {
32 get { return intPageSize; }
33 set { intPageSize = value; }
34 }
35 ///<summary>
36 /// 数据总数
37 ///</summary>
38 privateint intRecordCount;
39 publicnewint RecordCount
40 {
41 get { return intRecordCount; }
42 set { intRecordCount = value; }
43 }
44 }


------------------------------------------------------------------------------------------------------------------------------------------------

再来看看这控件怎么用吧

<Feli:Pager ID="fpgHistoryList" CssClass="felipager_main" runat="server" OnPageIndexChanged="fpgHistoryList_PageIndexChanged" /> 

当然,还需要设置每页显示的记录数及数据总数

this.fpgHistoryList.PageSize = 20;

this.fpgHistoryList.RecordCount = 600;

还有分页事件

分页事件
1 ///<summary>
2 /// 分页事件
3 ///</summary>
4 protectedvoid fpgHistoryList_PageIndexChanged(object sender, FeliControls.PageChangedEventArgs e)
5 {
6 BindPagedData(e.CurrentPageIndex);
7 }

到这,就全部结束了。。。(各CSS样式,可根据需要自己定义)

点此下载全部代码

初学的成果,难免有不完善或错误的地方,若发现了,还请指出,不胜感激!!!

posted @ 2011-07-21 15:33  up-Henson  阅读(1533)  评论(9编辑  收藏  举报