WinForm轻松实现自定义分页 (转载)

转载至http://xuzhihong1987.blog.163.com/blog/static/267315872011315114240140/

以前都是做web开发,最近接触了下WinForm,发现WinForm分页控件好像都没有,网上搜索了一下,发现有很多网友写的分页控件,分页效果应该都能实现吧,只是其风格都不是很符合我想要的。做web的时候,我习惯了Extjs的Grid分页效果,所以也想在WinForm中做个类似的效果,所以咬咬牙,做个山寨版本的吧,虽然自己写费时费力,在项目进度考虑中不是很可取,但是还是特别想山寨一回,做自己喜欢的风格。

按照惯例,还是先看看实现效果图吧(有图有真像,才好继续下文呀)

应用效果:(效果有点难看,因为我是刚装的

xp系统,还是经典主题,如果换成Win7系统或其他主题,效果还是会很不错的)

我们要做的就是上图显示的一个自定义控件,这个效果参考自我做

web开发使用的Extjs之Grid的分页效果(如下图)

Extjs的动画效果我们暂时就不实现了,这里只做个外观看起来想像即可,完全一样就脱离“山寨”概念了,总要比人家差点吧,谁让咱是模仿呢!

言归正传,我们现在就看看具体怎么实现吧:

第一步:先布局

    注:我们创建的是用户自定义控件,而不是WinForm窗体

就是先做出个显示效果,这个布局很简单,在这就不多说,重点就是“首页、前一页、后一页、末页”图标,每个图标分两种,一是能点击的高亮效果,一个是灰色不不能点击。以下是套图:(大家如果不喜欢,可以去做成自己喜欢的风格图片)

第二步:编写分页代码

   布局好了,那么第二步我们就要代码实现正确显示文字信息,分页事件,每页条数选择事件,公开属性和事件。以下是完整代码:

  1   /// <summary>
  2
  3     /// 声明委托
  4
  5     /// </summary>
  6
  7     /// <param name="e"></param>
  8
  9     public delegate void EventPagingHandler(EventArgs e);
 10
 11
 12
 13     public partial class Paging : UserControl
 14
 15     {
 16
 17
 18
 19
 20
 21         public Paging()
 22
 23         {
 24
 25             InitializeComponent();
 26
 27         }
 28
 29
 30
 31         public event EventPagingHandler EventPaging;
 32
 33
 34
 35         #region 公开属性
 36
 37
 38
 39
 40
 41         private int _pageSize = 50;
 42
 43         /// <summary>
 44
 45         /// 每页显示记录数(默认50)
 46
 47         /// </summary>
 48
 49         public int PageSize
 50
 51         {
 52
 53             get
 54
 55             {
 56
 57                 return _pageSize;
 58
 59             }
 60
 61             set
 62
 63             {
 64
 65                 if (value > 0)
 66
 67                 {
 68
 69                     _pageSize = value;
 70
 71                 }
 72
 73                 else
 74
 75                 {
 76
 77                     _pageSize = 50;
 78
 79                 }
 80
 81                 this.comboPageSize.Text = _pageSize.ToString();
 82
 83             }
 84
 85         }
 86
 87         private int _currentPage = 1;
 88
 89         /// <summary>
 90
 91         /// 当前页
 92
 93         /// </summary>
 94
 95         public int CurrentPage
 96
 97         {
 98
 99             get
100
101             {
102
103                 return _currentPage;
104
105             }
106
107             set
108
109             {
110
111                 if (value > 0)
112
113                 {
114
115                     _currentPage = value;
116
117                 }
118
119                 else
120
121                 {
122
123                     _currentPage = 1;
124
125                 }
126
127
128
129             }
130
131         }
132
133         private int _totalCount = 0;
134
135         /// <summary>
136
137         /// 总记录数
138
139         /// </summary>
140
141         public int TotalCount
142
143         {
144
145             get
146
147             {
148
149                 return _totalCount;
150
151             }
152
153             set
154
155             {
156
157                 if (value>=0)
158
159                 {
160
161                     _totalCount = value;
162
163                 }
164
165                 else
166
167                 {
168
169                     _totalCount = 0;
170
171                 }
172
173                 this.lblTotalCount.Text = this._totalCount.ToString();
174
175                 CalculatePageCount();
176
177                 this.lblRecordRegion.Text = GetRecordRegion();
178
179             }
180
181         }
182
183
184
185         private int _pageCount = 0;
186
187         /// <summary>
188
189         /// 页数
190
191         /// </summary>
192
193         public int PageCount
194
195         {
196
197             get
198
199             {
200
201                 return _pageCount;
202
203             }
204
205             set
206
207             {
208
209                 if (value>=0)
210
211                 {
212
213                     _pageCount = value;
214
215                 }
216
217                 else
218
219                 {
220
221                     _pageCount = 0;
222
223                 }
224
225                 this.lblPageCount.Text = _pageCount + "";
226
227             }
228
229         }
230
231
232
233        #endregion
234
235
236
237         /// <summary>
238
239         /// 计算页数
240
241         /// </summary>
242
243         private void CalculatePageCount()
244
245         {
246
247             if (this.TotalCount>0)
248
249             {
250
251                 this.PageCount = Convert.ToInt32(Math.Ceiling(Convert.ToDouble(this.TotalCount) / Convert.ToDouble(this.PageSize)));
252
253             }
254
255             else
256
257             {
258
259                 this.PageCount = 0;
260
261             }
262
263         }
264
265
266
267         /// <summary>
268
269         /// 获取显示记录区间(格式如:1-50)
270
271         /// </summary>
272
273         /// <returns></returns>
274
275         private string GetRecordRegion()
276
277         {
278
279             if (this.PageCount == 1) //只有一页
280
281             {
282
283                 return "1-" + this.TotalCount.ToString();
284
285             }
286
287             else  //有多页
288
289             {
290
291                 if(this.CurrentPage==1) //当前显示为第一页
292
293                 {
294
295                     return "1-"+this.PageSize;
296
297                 }
298
299                 else if(this.CurrentPage==this.PageCount) //当前显示为最后一页
300
301                 {
302
303                     return ((this.CurrentPage-1)*this.PageSize+1) +"-"+this.TotalCount;
304
305                 }
306
307                 else //中间页
308
309                 {
310
311                     return ((this.CurrentPage-1) * this.PageSize+1)   + "-" + this.CurrentPage  * this.PageSize;
312
313                 }
314
315
316             }
317
318         }
319
320
321
322
323
324         /// <summary>
325
326         /// 数据绑定
327
328         /// </summary>
329
330         public void Bind()
331
332         {
333
334             if (this.EventPaging != null)
335
336             {
337
338                 this.EventPaging(new EventArgs());
339
340             }
341
342             if (this.CurrentPage>this.PageCount)
343
344             {
345
346                 this.CurrentPage = this.PageCount;
347
348             }
349
350             this.txtBoxCurPage.Text = this.CurrentPage+"";
351
352             this.lblTotalCount.Text = this.TotalCount+"";
353
354             this.lblPageCount.Text = this.PageCount+"";
355
356             this.lblRecordRegion.Text = GetRecordRegion();
357
358             if (this.CurrentPage==1)
359
360             {
361
362                 this.btnFirst.Enabled = false;
363
364                 this.btnPrev.Enabled = false;
365
366                 this.btnFirst.Image = global::CHVM.Properties.Resources.page_first_disabled;
367
368                 this.btnPrev.Image = global::CHVM.Properties.Resources.page_prev_disabled;
369
370             }
371
372             else
373
374             {
375
376                 this.btnFirst.Enabled = true;
377
378                 this.btnPrev.Enabled = true;
379
380                 this.btnFirst.Image = global::CHVM.Properties.Resources.page_first;
381
382                 this.btnPrev.Image = global::CHVM.Properties.Resources.page_prev;
383
384             }
385
386             if (this.CurrentPage == this.PageCount)
387
388             {
389
390                 this.btnNext.Enabled = false;
391
392                 this.btnLast.Enabled = false;
393
394                 this.btnNext.Image = global::CHVM.Properties.Resources.page_next_disabled;
395
396                 this.btnLast.Image = global::CHVM.Properties.Resources.page_last_disabled;
397
398             }
399
400             else
401
402             {
403
404                 this.btnNext.Enabled = true;
405
406                 this.btnLast.Enabled = true;
407
408                 this.btnNext.Image = global::CHVM.Properties.Resources.page_next;
409
410                 this.btnLast.Image = global::CHVM.Properties.Resources.page_last;
411
412             }
413
414             if (this.TotalCount==0)
415
416             {
417
418                 this.btnFirst.Enabled = false;
419
420                 this.btnPrev.Enabled = false;
421
422                 this.btnNext.Enabled = false;
423
424                 this.btnLast.Enabled = false;
425
426                 this.btnFirst.Image = global::CHVM.Properties.Resources.page_first_disabled;
427
428                 this.btnPrev.Image = global::CHVM.Properties.Resources.page_prev_disabled;
429
430                 this.btnNext.Image = global::CHVM.Properties.Resources.page_next_disabled;
431
432                 this.btnLast.Image = global::CHVM.Properties.Resources.page_last_disabled;
433
434             }
435
436
437
438         }
439
440
441
442         private void btnFirst_Click(object sender, EventArgs e)
443
444         {
445
446             this.CurrentPage = 1;
447
448             this.Bind();
449
450         }
451
452
453
454         private void btnPrev_Click(object sender, EventArgs e)
455
456         {
457
458             this.CurrentPage -= 1;
459
460             this.Bind();
461
462         }
463
464
465
466         private void btnNext_Click(object sender, EventArgs e)
467
468         {
469
470             this.CurrentPage += 1;
471
472             this.Bind();
473
474         }
475
476
477
478         private void btnLast_Click(object sender, EventArgs e)
479
480         {
481
482             this.CurrentPage = this.PageCount;
483
484             this.Bind();
485
486         }
487
488
489
490         /// <summary>
491
492         ///  改变每页条数
493
494         /// </summary>
495
496         /// <param name="sender"></param>
497
498         /// <param name="e"></param>
499
500         private void comboPageSize_SelectedIndexChanged(object sender, EventArgs e)
501
502         {
503
504             this.PageSize = Convert.ToInt32(comboPageSize.Text);
505
506             this.Bind();
507
508         }
509
510
511
512 }
513
514
515
516 这里重点提两点:一是图片切换:
517
518 this.btnFirst.Image = global::CHVM.Properties.Resources.page_first_disabled;
519
520 Image对象是在Properties.Resource.resx中自动生成的,代码如下:
521
522         internal static System.Drawing.Bitmap page_first {
523
524             get {
525
526                 object obj = ResourceManager.GetObject("page-first", resourceCulture);
527
528                 return ((System.Drawing.Bitmap)(obj));
529
530             }
531
532         }
533
534
535
536         internal static System.Drawing.Bitmap page_first_disabled {
537
538             get {
539
540                 object obj = ResourceManager.GetObject("page_first_disabled", resourceCulture);
541
542                 return ((System.Drawing.Bitmap)(obj));
543
544             }
545
546     }
547
548 二是应用了委托事件:我们在这定义了一个分页事件
549
550 public event EventPagingHandler EventPaging;
551
552 在数据绑定方法中实现它:
553
554 /// <summary>
555
556         /// 数据绑定
557
558         /// </summary>
559
560         public void Bind()
561
562         {
563
564             if (this.EventPaging != null)
565
566             {
567
568                 this.EventPaging(new EventArgs());
569
570             }
571
572             //… 以下省略
573
574 }
575
576 这里需要大家对C#的委托和事件有一定的了解,不清楚的可以直接使用,或者先去查阅相关参考资料,这里我们就不谈委托机制了。
577
578
579
580 第三步:应用
581
582 值得一提的是,WinForm并不能直接把用户自定控件往Windows窗体中拖拽,而自动生成实例(ASP.NET是可以直接拖拽的)。那么如果我们需要在应用中使用,只能自己修改Desginer.cs代码了。
583
584 先声明:
585
586 private CHVM.PagingControl.Paging paging1;
587
588 然后在InitializeComponent()方法中实例化:
589
590 this.paging1 = new CHVM.PagingControl.Paging();
591
592     //
593
594     // paging1
595
596     //
597
598     this.paging1.CurrentPage = 1;
599
600     this.paging1.Location = new System.Drawing.Point(3, 347);
601
602     this.paging1.Name = "paging1";
603
604     this.paging1.PageCount = 0;
605
606     this.paging1.PageSize = 50;
607
608     this.paging1.Size = new System.Drawing.Size(512, 30);
609
610     this.paging1.TabIndex = 8;
611
612  this.paging1.TotalCount = 0;
613
614 //在这里注册事件
615
616 this.paging1.EventPaging += new CHVM.PagingControl.EventPagingHandler(this.paging1_EventPaging); 

加完后就能看到效果了,相当于托了一个分页控件的效果:(如下图所示)

最后在事件中加入分页事件需要执行的代码:

  1  /// <summary>
  2
  3         /// 分页事件
  4
  5         /// </summary>
  6
  7         /// <param name="e"></param>
  8
  9         private void paging1_EventPaging(EventArgs e)
 10
 11         {
 12
 13             GvDataBind();   //DataGridView数据绑定
 14
 15         }
 16
 17         /// <summary>
 18
 19         /// 查询
 20
 21         /// </summary>
 22
 23         /// <param name="sender"></param>
 24
 25         /// <param name="e"></param>
 26
 27         private void btnQuery_Click(object sender, EventArgs e)
 28
 29         {
 30
 31             paging1_EventPaging(e);
 32
 33         }
 34
 35         /// <summary>
 36
 37         /// gvOperateLogList 数据邦定
 38
 39         /// </summary>
 40
 41         private void GvDataBind()
 42
 43         {
 44
 45             PagingCondition paging = new PagingCondition()
 46
 47             {
 48
 49                 startIndex=paging1.CurrentPage,
 50
 51                 pageSize = paging1.PageSize
 52
 53             };
 54
 55             MultiCondition condition = new MultiCondition();
 56
 57             condition.DateSign="FOperateTime";
 58
 59             condition.BeginDate = dtBegin.Value;
 60
 61             condition.EndDate = dtEnd.Value;
 62
 63             if (comboOperator.Text != "")
 64
 65             {
 66
 67                 condition.Dict.Add("FOperator", comboOperator.Text);
 68
 69             }
 70
 71             if (comboType.Text != "")
 72
 73             {
 74
 75                 condition.Dict.Add("FType", comboType.Text);
 76
 77             }
 78
 79             if (comboObject.Text != "")
 80
 81             {
 82
 83                 condition.Dict.Add("FOptObject", comboObject.Text);
 84
 85             }
 86
 87             if (txtBoxContent.Text != "")
 88
 89             {
 90
 91                 condition.Dict.Add("FContent", txtBoxContent.Text);
 92
 93             }
 94
 95             DataTable dt = GetByCondition(paging, condition);
 96
 97             paging1.TotalCount = Convert.ToInt32(dt.TableName);
 98
 99             gvOperateLogList.DataSource = dt;
100
101             gvOperateLogList.Columns.Clear();
102
103             var dict = GetGvColumnsDict();
104
105             DataGridViewHelp.DisplayColList(gvOperateLogList, dict);
106
107         }

注:MultiCondition、PagingCondition是我专门针对分页综合查询定义的两个类,兴趣的话可以去了解一下:

查询条件就统一定义在MultiCondition中(详见:http://xuzhihong1987.blog.163.com/blog/static/267315872011294150763 ),

PagingCondition是分页条件(详见: http://xuzhihong1987.blog.163.com/blog/static/2673158720112941950801 ),

Extjs+LINQ轻松实现高级综合查询:

http://xuzhihong1987.blog.163.com/blog/static/2673158720112943356111/

其他:

 1  /// <summary>
 2
 3         /// gv显示列设置
 4
 5         /// </summary>
 6
 7         /// <returns></returns>
 8
 9         public Dictionary<string, string> GetGvColumnsDict()
10
11         {
12
13             Dictionary<string, string> dict = new Dictionary<string, string>();
14
15             dict.Add("FTYPE", "操作类型");
16
17             dict.Add("FOPTOBJECT", "操作对象");
18
19             dict.Add("FCONTENT", "操作内容");
20
21             dict.Add("FOperator", "操作人员");
22
23             return dict;
24
25         }
26
27
28
29 DataGridViewHelp.DisplayColList是一个静态方法,为一个辅助类:
30
31         /// <summary>
32
33         /// 替换列表
34
35         /// </summary>
36
37         /// <param name="dgv">类表名称</param>
38
39         /// <param name="dic">数据</param>
40
41         /// <param name="isRM">是否显示序列号</param>
42
43         public static void DisplayColList(DataGridView dgv, Dictionary<string, string> dic)//, bool isRM
44
45         {
46
47             _dgv = dgv;
48
49             dgv.RowsDefaultCellStyle.BackColor = Color.FromArgb(255, 255, 255);//第一行
50
51             dgv.AlternatingRowsDefaultCellStyle.BackColor = Color.FromArgb(231, 232, 239);//第二行
52
53             dgv.GridColor = Color.FromArgb(207, 208, 216);//
54
55             dgv.RowTemplate.Height = 25;//列宽
56
57             dgv.AllowUserToAddRows=false;//无空行
58
59             dgv.CellBorderStyle = DataGridViewCellBorderStyle.SingleVertical;
60
61             dgv.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
62
63             dgv.AllowUserToOrderColumns = true;
64
65             dgv.RowPostPaint += new DataGridViewRowPostPaintEventHandler(dgv_RowPostPaint);
66
67             dgv.CellPainting += new DataGridViewCellPaintingEventHandler(dgv_CellPainting);//列头样式
68
69             dgv.CellFormatting += new DataGridViewCellFormattingEventHandler(dgv_CellFormatting);//选中行样式
70
71
72
73             foreach (KeyValuePair<string, string> cl in dic)
74
75             {
76
77                 dgv.AutoGenerateColumns = false;
78
79                 DataGridViewTextBoxColumn obj = new DataGridViewTextBoxColumn();
80
81                 obj.DataPropertyName = cl.Key;
82
83                 obj.HeaderText = cl.Value;
84
85                 obj.Name = cl.Key;
86
87                 obj.Width = 100;
88
89                 //obj.DefaultCellStyle.Padding.All = 10;
90
91                 obj.Resizable = DataGridViewTriState.True;
92
93                 dgv.Columns.AddRange(new DataGridViewColumn[] { obj });
94
95             }
96
97         }
98
99  

到此实现就全部完成了,运行效果后就是前面所示的效果!也可以动态修改每页条数。

说在最后,改功能简单是简单,但是涉及到很多知识点,委托、事件、

DataGridView数据动态绑定,综合查询,我这里用的是Oracle数据库,如果用LINQ语法的话查询数据会比较方便,写起代码也会显得很优雅。

1 /// <summary>        /// 获取条件查询数据        /// </summary>        /// <param name="paging"></param>        /// <param name="conditon"></param>        /// <returns></returns>        private DataTable GetByCondition(PagingCondition paging, MultiCondition conditon)        {            string strSql = "select * from TOperateLog ";            string strSqlGetCount = "select count(1) from TOperateLog ";            string strWhere = " where 1=1 ";            if (conditon != null)            {                if (conditon.DateSign == "FOperateTime") //操作日期                {                    if (conditon.BeginDate != DateTime.MinValue)                    {                        strWhere += string.Format(" and FOperateTime>=‘{0}‘", conditon.BeginDate.ToString("yyyy-MM-dd HH:mm:ss"));                    }                    if (conditon.EndDate != DateTime.MaxValue)                    {                        strWhere += string.Format(" and FOperateTime<=‘{0}‘", conditon.EndDate.AddDays(1).ToString("yyyy-MM-dd HH:mm:ss"));                    }                }                var dict = conditon.Dict;                if (dict != null)                {                    foreach (var key in dict.Keys)                    {                        if (key.Equals("FType")) //操作类型                        {                            strWhere += string.Format(" and FType=‘{0}‘", dict[key]);                        }                        if (key.Equals("FOperator")) //操作人员                        {                            strWhere += string.Format(" and FOperator=‘{0}‘", dict[key]);                        }                        else if (key.Equals("FOptObject")) //操作对象                        {                            strWhere += string.Format(" and FOptObject=‘{0}‘", dict[key]);                        }                        else if (key.Equals("FContent")) //操作内容                        {                            strWhere += string.Format(" and FContent like ‘%{0}%‘", dict[key]);                        }                    }                }            }            strWhere += " order by FOperateTime ";            strSql += strWhere;            strSqlGetCount += strWhere;            if (paging != null)            {                if (paging.needPaging)                {                    //strSql = string.Format("select * from ( {0} ) where ROWNUM>={1} and ROWNUM<={2}", strSql, paging.startIndex, paging.startIndex + paging.pageSize-1);                    strSql = string.Format("select * from (select T.*,RowNum  RN from ({0})T where ROWNUM <={1}) where RN>={2} ",strSql, paging.startIndex + paging.pageSize - 1,paging.startIndex);                }            }            DataTable dt = DataCon.Query(strSql).Tables[0];            dt.TableName = DataCon.GetSingle(strSqlGetCount)+"";            return dt;        }

WinForm轻松实现自定义分页 (转载)

时间: 2024-09-30 07:23:25

WinForm轻松实现自定义分页 (转载)的相关文章

Cookie、Session和自定义分页

cookie Cookie的由来 大家都知道HTTP协议是无状态的. 无状态的意思是每次请求都是独立的,它的执行情况和结果与前面的请求和之后的请求都无直接关系,它不会受前面的请求响应情况直接影响,也不会直接影响后面的请求响应情况. 一句有意思的话来描述就是人生只如初见,对服务器来说,每次的请求都是全新的. 状态可以理解为客户端和服务器在某次会话中产生的数据,那无状态的就以为这些数据不会被保留.会话中产生的数据又是我们需要保存的,也就是说要"保持状态".因此cookie就是在这样一个场景

laravel5自定义分页

laravel5分页处理与laravel4略有区别,laravel5提供了更方便的处理方式,可以方便满足不同分页展示. laravel4自定义分页:http://php2012web.blog.51cto.com/5585213/1539601 laravel分页处理有分两个入口,即两个处理对象: DB操作分页       Illuminate\Database\Query\Builder ORM操作分页   Illuminate\Database\Eloquent\Builder DB操作分页

JSP自定义分页标签TAG

首先我们需要在WEB-INF/tld/目录下创建page.tld文件 <?xml version="1.0" encoding="ISO-8859-1"?> <taglib> <tlib-version>1.0</tlib-version> <jsp-version>1.2</jsp-version> <short-name>page</short-name> <u

gridview自定义分页 aspNetPager用法

这几天做gridview分页,自带的分页不好用.从网上搜刚开始搜了一个aspNetPager.dll,替换原来的一个dll,自己设置了一些,比如这个控件不显示中文,后来我改成中文的"上一页"."下一页"."首页""尾页",把ShowPageIndexBox设置为默认true,这样当前页也显示了,还能跳转. 还设置了 显示自定义区域,默认是不显示了,我改成left,然后再设置下自定义的html,结果就可以显示了,我显示的是 一共

django 自定义分页模块

django 自定义分页模块 from django.shortcuts import render, HttpResponse, redirect from django.utils.safestring import mark_safe class Page(object): def __init__(self, current_page): self.current_page = int(current_page) @property def start(self): return (se

thinkphp自定义分页效果

TP自带了一个分页函数,挺方便使用的. 下面是我的使用方法: 1 /*****************分页显示start*************************/ 2 $arr_page=$this->page($user,1); 3 $show=$arr_page['show']; 4 $Page=$arr_page['Page']; 5 $article = $user->order('now')->limit($Page->firstRow.','.$Page-&g

主攻ASP.NET.4.5.1 MVC5.0之重生:创建UIHelper通用自定义分页和选择开关与PagesHelper和IsSelect简单用法

@helper放入地方 分页效果 选择开关编辑调用 <dl> <dd class="dc1">是否主管:</dd> <dd> @UIHelper.IsSelect("IsManager",Model.IsManager.ToString()); </dd> </dl> 分页调用 <div class="rg5"> @UIHelper.PagesHelper(Vie

python/Djangof分页与自定义分页

python/Djangof分页与自定义分页 Django分页 1 ##============================================分页======================================================= 2 # current_pagc = request.GET.get('page') 3 # from django.core.paginator import Paginator,Page 4 # # result = m

PHPCMS V9二次开发自定义分页函数的解决方案

下面为大家分享一个PHPCMS V9二次开发自定义分页函数的方法. 方法如下: 首先打开 phpcms\libs\functions\global.func.php这个文件,找到分页函数,复制一下,粘贴到默认分页函数的下面,重新命名,比如我的就命名为wz_pages,保存. 打开 phpcms/libs/classes/template_cache.class.php,找到207行的: $str .= '$pages = pages($'.$op.'_total, $page, $pagesiz