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页的时候, ...
随机推荐
- php中向mysql插入数据
$sql='insert into news(title,subtitle,source,publishtime,content,image,author) values("'.unico ...
- 安装Sublime Text 3插件的方法
直接安装 安装Sublime text 3插件很方便,可以直接下载安装包解压缩到Packages目录(菜单->preferences->packages). 使用Package Contr ...
- Javascript高级程序设计——在HTML中使用Javascript
<script>元素 向HTML页面中插入Javascript的主要方法,就是使用<script>元素,<script>元素有六个属性: async:可选.表示应该 ...
- 0821找不到Command Line Utility的解决方案
在Object-C基础教程中写到,要求选择Xcode中Mac OS X - Command Line Utility - Foundation Tool 但在Xcode4.5中Mac OS X中没有C ...
- All Kind Of Conference(随时更新...)
收集一些前端开发的各种会议,里面有视频或者PPT,随时查看都还是很有收获的.还有要向这些演讲的前辈看齐- AC 2015:http://ac.alloyteam.com/2015/ AC 2016:h ...
- python 集合 -----直接用逗号连接的是元组,不是list
t = 12345, 54321, 'hello!' >>> t[0] 12345 >>> t (12345, 54321, 'hello!') 元组:元组由逗号分 ...
- linux各文件夹的作用
文章转载自:http://www.cnblogs.com/amboyna/archive/2008/02/16/1070474.html 精------------------------------ ...
- 解压.tar.gz出错gzip: stdin: not in gzip format tar: /Child returned status 1 tar: Error is not recoverable: exiting now
先查看文件真正的属性是什么? [root@xxxxx ~]# tar -zxvf tcl8.4.16-src.tar.gz gzip: stdin: not in gzip format tar: ...
- 术&道
技术分为术和道两种. 具体做事的方法为术:做事的原理和原则是道. 追求术的人一辈子工作很辛苦,只有掌握了道的本质和精髓才能永远游刃有余. 在纷繁的选择面前, 不知到哪些是对的没关系, 知道哪些是不好的 ...
- 如何修复IIS7
修复错误 运行命令提示符 fsutil resource setautoreset true c:\ 打开运行输入 services.msc 启动Windows Process Act ...