转载至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轻松实现自定义分页 (转载)的更多相关文章

  1. winform中DataGridView实现分页功能

    WinForm轻松实现自定义分页 (转载) WinForm轻松实现自定义分页 (转载)   转载至http://xuzhihong1987.blog.163.com/blog/static/26731 ...

  2. C# DataGridView自定义分页控件

    好些日子不仔细写C#代码了,现在主要是Java项目,C#.Net相关项目不多了,有点手生了,以下代码不足之处望各位提出建议和批评. 近日闲来无事想研究一下自定义控件,虽然之前也看过,那也仅限于皮毛,粗 ...

  3. 雷林鹏分享:jQuery EasyUI 数据网格 - 自定义分页

    jQuery EasyUI 数据网格 - 自定义分页 数据网格(datagrid)内置一个很好特性的分页功能,自定义也相当简单.在本教程中,我们将创建一个数据网格(datagrid),并在分页工具栏上 ...

  4. Android Launcher分析和修改11——自定义分页指示器(paged_view_indicator)

    Android4.0的Launcher自带了一个简单的分页指示器,就是Hotseat上面那个线段,这个本质上是一个ImageView利用.9.png图片做,效果实在是不太美观,用测试人员的话,太丑了. ...

  5. asp.net webform 自定义分页控件

    做web开发一直用到分页控件,自己也动手实现了个,使用用户自定义控件. 翻页后数据加载使用委托,将具体实现放在在使用分页控件的页面进行注册. 有图有真相,给个直观的认识: 自定义分页控件前台代码: & ...

  6. Python之路【第十九篇】自定义分页实现(模块化)

    自定义分页 1.目的&环境准备 目的把分页写成一个模块的方式然后在需要分页的地方直接调用模块就行了. 环境准备Django中生成一个APP并且注册,配置URL&Views 配置URL ...

  7. MVC下分页的自定义分页一种实现

    1.引言 在MVC开发中我们经常会对数据进行分页的展示.通过分页我们可以从服务端获取指定的数据来进行展示.这样既节约了数据库查询的时间也节约了网络传输的数据量.在MVC开发中使用的比较多的应该是MVC ...

  8. Django自定义分页、bottle、Flask

    一.使用django实现之定义分页 1.自定义分页在django模板语言中,通过a标签实现; 2.前段a标签使用<a href="/user_list/?page=1"> ...

  9. Mvc自定义分页控件

    MVC开发分页常常使用第三方控件,生成的分页HTML带有版权申明,虽然免费,但是总有的别扭.于是,某日,楼主闲来蛋疼,折腾了个自定义分页控件: 先来展示下效果图: 1>当分页不超过10页的时候, ...

随机推荐

  1. SQLServer安装错误之--->无法打开项 UNKNOWN\Components\DA42BC89BF25F5BD0AF18C3B9B1A1EE8\c1c4f01781cc94c4c8fb1542c0981a2a

    – 错误 1402.无法打开项 UNKNOWN\Components\7ABFE44842C12B390AF18C3B9B1A1EE8\54D21D49F3A8C1C49AC11A1B6445A83E ...

  2. uva10870 递推关系Recurrences

    Consider recurrent functions of the following form:f(n) = a1f(n - 1) + a2f(n - 2) + a3f(n - 3) + : : ...

  3. 清北学堂模拟day4 捡金币

    [问题描述]小空正在玩一个叫做捡金币的游戏.游戏在一个被划分成 n行 n列的网格状场地中进行.每一个格子中都放着若干金币,并且金币的数量会随着时间而不断变化. 小空的任务就是在网格中移动,拾取尽量多的 ...

  4. Android 实现简单音乐播放器(一)

    今天掐指一算,学习Android长达近两个月了,今天开始,对过去一段时间的学习收获以及遇到的疑难杂症做一些总结. 简单音乐播放器是我自己完成的第一个功能较为完整的APP,可以说是我的Android学习 ...

  5. FineUI第十七天---- 表格之扩展列

    {          sb.AppendFormat(]); 1.通过表格的SelectedRowIndexArray获得选中行的索引号列表: 2.通过表格的DataKeys(二维数组)获取本行的数据 ...

  6. iOS企业级开发初级课程-表视图(13集)

    首先了解了表视图的组成.表视图类的构成.表视图的分类以及表视图的两个重要协议(委托协议和数据源协议),对表视图有了一个整体上的认识.接下来我们掌握了如何实现简单表视图和分节表视图,以及表视图中索引.搜 ...

  7. [OpenJudge0054]特务会议召开

    [OpenJudge0054]特务会议召开 试题描述 在敌占区的特务时常会碰头.敌占区有n个城市,为保证安全,中央经过侦查,只选择了n-1条较安全的道路作为特务们碰头可以走的道路.每次开会,中央会选择 ...

  8. 网络之AFNetsorking

    AFNetsorking作为功能全面的网络第三方,既通俗好用又与时俱进-及时的更新使用了NSURLSession,不得不爱. AFNetsorking使用: 1,AFNetsorking GET请求 ...

  9. Caffe学习系列(11):数据可视化环境(python接口)配置

    参考:http://www.cnblogs.com/denny402/p/5088399.html 这节配置python接口遇到了不少坑. 1.我是利用anaconda来配置python环境,在将ca ...

  10. (转)android图片压缩总结

    原文地址:http://blog.csdn.net/cherry609195946/article/details/9264409 一.图片的存在形式 1.文件形式(即以二进制形式存在于硬盘上)2.流 ...