WinForm轻松实现自定义分页 (转载)
转载至http://xuzhihong1987.blog.163.com/blog/static/267315872011315114240140/
以前都是做web开发,最近接触了下WinForm,发现WinForm分页控件好像都没有,网上搜索了一下,发现有很多网友写的分页控件,分页效果应该都能实现吧,只是其风格都不是很符合我想要的。做web的时候,我习惯了Extjs的Grid分页效果,所以也想在WinForm中做个类似的效果,所以咬咬牙,做个山寨版本的吧,虽然自己写费时费力,在项目进度考虑中不是很可取,但是还是特别想山寨一回,做自己喜欢的风格。
按照惯例,还是先看看实现效果图吧(有图有真像,才好继续下文呀)
应用效果:(效果有点难看,因为我是刚装的
xp系统,还是经典主题,如果换成Win7系统或其他主题,效果还是会很不错的)
我们要做的就是上图显示的一个自定义控件,这个效果参考自我做
web开发使用的Extjs之Grid的分页效果(如下图)
Extjs的动画效果我们暂时就不实现了,这里只做个外观看起来想像即可,完全一样就脱离“山寨”概念了,总要比人家差点吧,谁让咱是模仿呢!
言归正传,我们现在就看看具体怎么实现吧:
第一步:先布局
注:我们创建的是用户自定义控件,而不是WinForm窗体
就是先做出个显示效果,这个布局很简单,在这就不多说,重点就是“首页、前一页、后一页、末页”图标,每个图标分两种,一是能点击的高亮效果,一个是灰色不不能点击。以下是套图:(大家如果不喜欢,可以去做成自己喜欢的风格图片)
第二步:编写分页代码
布局好了,那么第二步我们就要代码实现正确显示文字信息,分页事件,每页条数选择事件,公开属性和事件。以下是完整代码:
/// <summary> /// 声明委托 /// </summary> /// <param name="e"></param> public delegate void EventPagingHandler(EventArgs e); public partial class Paging : UserControl { public Paging() { InitializeComponent(); } public event EventPagingHandler EventPaging; #region 公开属性 private int _pageSize = ; /// <summary> /// 每页显示记录数(默认50) /// </summary> public int PageSize { get { return _pageSize; } set { if (value > ) { _pageSize = value; } else { _pageSize = ; } this.comboPageSize.Text = _pageSize.ToString(); } } private int _currentPage = ; /// <summary> /// 当前页 /// </summary> public int CurrentPage { get { return _currentPage; } set { if (value > ) { _currentPage = value; } else { _currentPage = ; } } } private int _totalCount = ; /// <summary> /// 总记录数 /// </summary> public int TotalCount { get { return _totalCount; } set { if (value>=) { _totalCount = value; } else { _totalCount = ; } this.lblTotalCount.Text = this._totalCount.ToString(); CalculatePageCount(); this.lblRecordRegion.Text = GetRecordRegion(); } } private int _pageCount = ; /// <summary> /// 页数 /// </summary> public int PageCount { get { return _pageCount; } set { if (value>=) { _pageCount = value; } else { _pageCount = ; } this.lblPageCount.Text = _pageCount + ""; } } #endregion /// <summary> /// 计算页数 /// </summary> private void CalculatePageCount() { if (this.TotalCount>) { this.PageCount = Convert.ToInt32(Math.Ceiling(Convert.ToDouble(this.TotalCount) / Convert.ToDouble(this.PageSize))); } else { this.PageCount = ; } } /// <summary> /// 获取显示记录区间(格式如:1-50) /// </summary> /// <returns></returns> private string GetRecordRegion() { if (this.PageCount == ) //只有一页 { return "1-" + this.TotalCount.ToString(); } else //有多页 { if(this.CurrentPage==) //当前显示为第一页 { return "1-"+this.PageSize; } else if(this.CurrentPage==this.PageCount) //当前显示为最后一页 { return ((this.CurrentPage-)*this.PageSize+) +"-"+this.TotalCount; } else //中间页 { return ((this.CurrentPage-) * this.PageSize+) + "-" + this.CurrentPage * this.PageSize; } } } /// <summary> /// 数据绑定 /// </summary> public void Bind() { if (this.EventPaging != null) { this.EventPaging(new EventArgs()); } if (this.CurrentPage>this.PageCount) { this.CurrentPage = this.PageCount; } this.txtBoxCurPage.Text = this.CurrentPage+""; this.lblTotalCount.Text = this.TotalCount+""; this.lblPageCount.Text = this.PageCount+""; this.lblRecordRegion.Text = GetRecordRegion(); if (this.CurrentPage==) { this.btnFirst.Enabled = false; this.btnPrev.Enabled = false; this.btnFirst.Image = global::CHVM.Properties.Resources.page_first_disabled; this.btnPrev.Image = global::CHVM.Properties.Resources.page_prev_disabled; } else { this.btnFirst.Enabled = true; this.btnPrev.Enabled = true; this.btnFirst.Image = global::CHVM.Properties.Resources.page_first; this.btnPrev.Image = global::CHVM.Properties.Resources.page_prev; } if (this.CurrentPage == this.PageCount) { this.btnNext.Enabled = false; this.btnLast.Enabled = false; this.btnNext.Image = global::CHVM.Properties.Resources.page_next_disabled; this.btnLast.Image = global::CHVM.Properties.Resources.page_last_disabled; } else { this.btnNext.Enabled = true; this.btnLast.Enabled = true; this.btnNext.Image = global::CHVM.Properties.Resources.page_next; this.btnLast.Image = global::CHVM.Properties.Resources.page_last; } if (this.TotalCount==) { this.btnFirst.Enabled = false; this.btnPrev.Enabled = false; this.btnNext.Enabled = false; this.btnLast.Enabled = false; this.btnFirst.Image = global::CHVM.Properties.Resources.page_first_disabled; this.btnPrev.Image = global::CHVM.Properties.Resources.page_prev_disabled; this.btnNext.Image = global::CHVM.Properties.Resources.page_next_disabled; this.btnLast.Image = global::CHVM.Properties.Resources.page_last_disabled; } } private void btnFirst_Click(object sender, EventArgs e) { this.CurrentPage = ; this.Bind(); } private void btnPrev_Click(object sender, EventArgs e) { this.CurrentPage -= ; this.Bind(); } private void btnNext_Click(object sender, EventArgs e) { this.CurrentPage += ; this.Bind(); } private void btnLast_Click(object sender, EventArgs e) { this.CurrentPage = this.PageCount; this.Bind(); } /// <summary> /// 改变每页条数 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void comboPageSize_SelectedIndexChanged(object sender, EventArgs e) { this.PageSize = Convert.ToInt32(comboPageSize.Text); this.Bind(); } } 这里重点提两点:一是图片切换: this.btnFirst.Image = global::CHVM.Properties.Resources.page_first_disabled; Image对象是在Properties.Resource.resx中自动生成的,代码如下: internal static System.Drawing.Bitmap page_first { get { object obj = ResourceManager.GetObject("page-first", resourceCulture); return ((System.Drawing.Bitmap)(obj)); } } internal static System.Drawing.Bitmap page_first_disabled { get { object obj = ResourceManager.GetObject("page_first_disabled", resourceCulture); return ((System.Drawing.Bitmap)(obj)); } } 二是应用了委托事件:我们在这定义了一个分页事件 public event EventPagingHandler EventPaging; 在数据绑定方法中实现它: /// <summary> /// 数据绑定 /// </summary> public void Bind() { if (this.EventPaging != null) { this.EventPaging(new EventArgs()); } //… 以下省略 } 这里需要大家对C#的委托和事件有一定的了解,不清楚的可以直接使用,或者先去查阅相关参考资料,这里我们就不谈委托机制了。 第三步:应用 值得一提的是,WinForm并不能直接把用户自定控件往Windows窗体中拖拽,而自动生成实例(ASP.NET是可以直接拖拽的)。那么如果我们需要在应用中使用,只能自己修改Desginer.cs代码了。 先声明: private CHVM.PagingControl.Paging paging1; 然后在InitializeComponent()方法中实例化: this.paging1 = new CHVM.PagingControl.Paging(); // // paging1 // this.paging1.CurrentPage = ; this.paging1.Location = new System.Drawing.Point(, ); this.paging1.Name = "paging1"; this.paging1.PageCount = ; this.paging1.PageSize = ; this.paging1.Size = new System.Drawing.Size(, ); this.paging1.TabIndex = ; this.paging1.TotalCount = ; //在这里注册事件 this.paging1.EventPaging += new CHVM.PagingControl.EventPagingHandler(this.paging1_EventPaging);
加完后就能看到效果了,相当于托了一个分页控件的效果:(如下图所示)
最后在事件中加入分页事件需要执行的代码:
/// <summary> /// 分页事件 /// </summary> /// <param name="e"></param> private void paging1_EventPaging(EventArgs e) { GvDataBind(); //DataGridView数据绑定 } /// <summary> /// 查询 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnQuery_Click(object sender, EventArgs e) { paging1_EventPaging(e); } /// <summary> /// gvOperateLogList 数据邦定 /// </summary> private void GvDataBind() { PagingCondition paging = new PagingCondition() { startIndex=paging1.CurrentPage, pageSize = paging1.PageSize }; MultiCondition condition = new MultiCondition(); condition.DateSign="FOperateTime"; condition.BeginDate = dtBegin.Value; condition.EndDate = dtEnd.Value; if (comboOperator.Text != "") { condition.Dict.Add("FOperator", comboOperator.Text); } if (comboType.Text != "") { condition.Dict.Add("FType", comboType.Text); } if (comboObject.Text != "") { condition.Dict.Add("FOptObject", comboObject.Text); } if (txtBoxContent.Text != "") { condition.Dict.Add("FContent", txtBoxContent.Text); } DataTable dt = GetByCondition(paging, condition); paging1.TotalCount = Convert.ToInt32(dt.TableName); gvOperateLogList.DataSource = dt; gvOperateLogList.Columns.Clear(); var dict = GetGvColumnsDict(); DataGridViewHelp.DisplayColList(gvOperateLogList, dict); }
注: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/
其他:
/// <summary> /// gv显示列设置 /// </summary> /// <returns></returns> public Dictionary<string, string> GetGvColumnsDict() { Dictionary<string, string> dict = new Dictionary<string, string>(); dict.Add("FTYPE", "操作类型"); dict.Add("FOPTOBJECT", "操作对象"); dict.Add("FCONTENT", "操作内容"); dict.Add("FOperator", "操作人员"); return dict; } DataGridViewHelp.DisplayColList是一个静态方法,为一个辅助类: /// <summary> /// 替换列表 /// </summary> /// <param name="dgv">类表名称</param> /// <param name="dic">数据</param> /// <param name="isRM">是否显示序列号</param> public static void DisplayColList(DataGridView dgv, Dictionary<string, string> dic)//, bool isRM { _dgv = dgv; dgv.RowsDefaultCellStyle.BackColor = Color.FromArgb(, , );//第一行 dgv.AlternatingRowsDefaultCellStyle.BackColor = Color.FromArgb(, , );//第二行 dgv.GridColor = Color.FromArgb(, , );// dgv.RowTemplate.Height = ;//列宽 dgv.AllowUserToAddRows=false;//无空行 dgv.CellBorderStyle = DataGridViewCellBorderStyle.SingleVertical; dgv.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill; dgv.AllowUserToOrderColumns = true; dgv.RowPostPaint += new DataGridViewRowPostPaintEventHandler(dgv_RowPostPaint); dgv.CellPainting += new DataGridViewCellPaintingEventHandler(dgv_CellPainting);//列头样式 dgv.CellFormatting += new DataGridViewCellFormattingEventHandler(dgv_CellFormatting);//选中行样式 foreach (KeyValuePair<string, string> cl in dic) { dgv.AutoGenerateColumns = false; DataGridViewTextBoxColumn obj = new DataGridViewTextBoxColumn(); obj.DataPropertyName = cl.Key; obj.HeaderText = cl.Value; obj.Name = cl.Key; obj.Width = ; //obj.DefaultCellStyle.Padding.All = 10; obj.Resizable = DataGridViewTriState.True; dgv.Columns.AddRange(new DataGridViewColumn[] { obj }); } }
到此实现就全部完成了,运行效果后就是前面所示的效果!也可以动态修改每页条数。
说在最后,改功能简单是简单,但是涉及到很多知识点,委托、事件、
DataGridView数据动态绑定,综合查询,我这里用的是Oracle数据库,如果用LINQ语法的话查询数据会比较方便,写起代码也会显得很优雅。
/// <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轻松实现自定义分页 (转载)的更多相关文章
- winform中DataGridView实现分页功能
WinForm轻松实现自定义分页 (转载) WinForm轻松实现自定义分页 (转载) 转载至http://xuzhihong1987.blog.163.com/blog/static/26731 ...
- C# DataGridView自定义分页控件
好些日子不仔细写C#代码了,现在主要是Java项目,C#.Net相关项目不多了,有点手生了,以下代码不足之处望各位提出建议和批评. 近日闲来无事想研究一下自定义控件,虽然之前也看过,那也仅限于皮毛,粗 ...
- 雷林鹏分享:jQuery EasyUI 数据网格 - 自定义分页
jQuery EasyUI 数据网格 - 自定义分页 数据网格(datagrid)内置一个很好特性的分页功能,自定义也相当简单.在本教程中,我们将创建一个数据网格(datagrid),并在分页工具栏上 ...
- Android Launcher分析和修改11——自定义分页指示器(paged_view_indicator)
Android4.0的Launcher自带了一个简单的分页指示器,就是Hotseat上面那个线段,这个本质上是一个ImageView利用.9.png图片做,效果实在是不太美观,用测试人员的话,太丑了. ...
- asp.net webform 自定义分页控件
做web开发一直用到分页控件,自己也动手实现了个,使用用户自定义控件. 翻页后数据加载使用委托,将具体实现放在在使用分页控件的页面进行注册. 有图有真相,给个直观的认识: 自定义分页控件前台代码: & ...
- Python之路【第十九篇】自定义分页实现(模块化)
自定义分页 1.目的&环境准备 目的把分页写成一个模块的方式然后在需要分页的地方直接调用模块就行了. 环境准备Django中生成一个APP并且注册,配置URL&Views 配置URL ...
- MVC下分页的自定义分页一种实现
1.引言 在MVC开发中我们经常会对数据进行分页的展示.通过分页我们可以从服务端获取指定的数据来进行展示.这样既节约了数据库查询的时间也节约了网络传输的数据量.在MVC开发中使用的比较多的应该是MVC ...
- Django自定义分页、bottle、Flask
一.使用django实现之定义分页 1.自定义分页在django模板语言中,通过a标签实现; 2.前段a标签使用<a href="/user_list/?page=1"> ...
- Mvc自定义分页控件
MVC开发分页常常使用第三方控件,生成的分页HTML带有版权申明,虽然免费,但是总有的别扭.于是,某日,楼主闲来蛋疼,折腾了个自定义分页控件: 先来展示下效果图: 1>当分页不超过10页的时候, ...
随机推荐
- NetBeans使用习惯:升级与保存配置
如何升级:点击 netbeans 的升级更新 ,即可升级版本:不推荐官网下载进行安装,否则会出现,以前的旧版本8.0的目录和8.0.1目录,虽然它会自动检测到以前版本的配置,提示导入... 如何备份: ...
- Cocos2D-X 学习笔记
1. 3.4final控制台创建项目后,安卓编译会失败,必须手动把cocos/平台/andorid/java/src目录里的文件复制到安卓项目的src文件夹即可 2. 安卓的文件目录与win的略有不同 ...
- select2
.select2-container .select2-choice { height: 34px; line-height: 34px; } .自定义 组件高度 在css 里面设置 .select2 ...
- 2015baidu复赛2 连接的管道(mst && 优先队列prim)
连接的管道 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submi ...
- window使用qt遇到的坑
1.window上的qt对图片的检测与识别不够完善.往往改了一个ui的背景图片,运行出来显示的却是旧的背景图片. 原因: 由于之前是项目与项目之间整合在一起,然后把ui_*_ui.h的临时文件也放在 ...
- Lvs原理
官方文档: http://www.linuxvirtualserver.org/zh/lvs1.html http://www.linuxvirtualserver.org/zh/lvs2.html ...
- FineUI第十八天---表格之事件的处理
表格之事件的处理: 1.事件参数: GridPageEventArgs:表格分页事件参数,对应onPageIndexChange事件. NewPageIndex:新页面的索引 GridSortEven ...
- BZOJ1500——维修序列
动态的最大子段和 就是splay啊,说一下GSS1吧,维护四个值,一个是这个区间和(下面说sum), 一个是从左边开始的最大和(下面说ls)和右边开始的最大和(下面说rs), 还有一个就是最大区间和( ...
- linux中tar命令用法
把常用的tar解压命令总结下,当作备忘: tar -c: 建立压缩档案 -x:解压 -t:查看内容 -r:向压缩归档文件末尾追加文件 -u:更新原压缩包中的文件 这五个是独立的命令,压缩解压都要用到其 ...
- 基于jquery的-获取短信验证码-倒计时
在制作短信验证的时候,需要做一个获取短信按钮,点击后显示倒计时, html代码如下: <input class="gain" type="button" ...