WinForm輕鬆實現自定義分頁 (轉載)

轉載至http://xuzhihong1987.blog.163.com/blog/static/267315872011315114240140/web

之前都是作web開發,最近接觸了下WinForm,發現WinForm分頁控件好像都沒有,網上搜索了一下,發現有不少網友寫的分頁控件,分頁效果應該都能實現吧,只是其風格都不是很符合我想要的。作web的時候,我習慣了Extjs的Grid分頁效果,因此也想在WinForm中作個相似的效果,因此咬咬牙,作個山寨版本的吧,雖然本身寫費時費力,在項目進度考慮中不是很可取,可是仍是特別想山寨一回,作本身喜歡的風格。數據庫

按照慣例,仍是先看看實現效果圖吧(有圖有真像,纔好繼續下文呀)ide

應用效果:(效果有點難看,由於我是剛裝的佈局

xp系統,仍是經典主題,若是換成Win7系統或其餘主題,效果仍是會很不錯的)動畫

 

咱們要作的就是上圖顯示的一個自定義控件,這個效果參考自我作this

web開發使用的Extjs之Grid的分頁效果(以下圖)spa

 

Extjs的動畫效果咱們暫時就不實現了,這裏只作個外觀看起來想像便可,徹底同樣就脫離「山寨」概念了,總要比人家差點吧,誰讓咱是模仿呢!3d

言歸正傳,咱們如今就看看具體怎麼實現吧:code

 

第一步:先佈局orm

    注:咱們建立的是用戶自定義控件,而不是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); 
View Code

 

加完後就能看到效果了,至關於託了一個分頁控件的效果:(以下圖所示)

最後在事件中加入分頁事件須要執行的代碼:

 

  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         }
View Code

 

注: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  
View Code

 

到此實現就所有完成了,運行效果後就是前面所示的效果!也能夠動態修改每頁條數。

說在最後,改功能簡單是簡單,可是涉及到不少知識點,委託、事件、

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;        }
View Code
相關文章
相關標籤/搜索