转载至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);