WinForm轻松实现自定义分页

来源:互联网 发布:数据挖掘 知乎 编辑:程序博客网 时间:2024/04/29 19:14

以前都是做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 = 50;        /// <summary>        /// 每页显示记录数(默认50)        /// </summary>        public int PageSize        {            get            {                return _pageSize;            }            set             {                if (value > 0)                {                    _pageSize = value;                }                else                {                    _pageSize = 50;                }                this.comboPageSize.Text = _pageSize.ToString();            }        }        private int _currentPage = 1;        /// <summary>        /// 当前页        /// </summary>        public int CurrentPage        {            get             {                return _currentPage;            }            set             {                if (value > 0)                {                    _currentPage = value;                }                else                {                    _currentPage = 1;                }                            }        }        private int _totalCount = 0;        /// <summary>        /// 总记录数        /// </summary>        public int TotalCount        {            get            {                return _totalCount;            }            set             {                if (value>=0)                {                    _totalCount = value;                }                 else                {                    _totalCount = 0;                }                this.lblTotalCount.Text = this._totalCount.ToString();                CalculatePageCount();                this.lblRecordRegion.Text = GetRecordRegion();            }        }         private int _pageCount = 0;        /// <summary>        /// 页数        /// </summary>        public int PageCount        {            get            {                return _pageCount;            }            set             {                if (value>=0)                {                    _pageCount = value;                }                 else                {                    _pageCount = 0;                }                this.lblPageCount.Text = _pageCount + "";            }        }        #endregion         /// <summary>        /// 计算页数        /// </summary>        private void CalculatePageCount()        {            if (this.TotalCount>0)            {                this.PageCount = Convert.ToInt32(Math.Ceiling(Convert.ToDouble(this.TotalCount) / Convert.ToDouble(this.PageSize)));            }            else            {                this.PageCount = 0;            }        }         /// <summary>        /// 获取显示记录区间(格式如:1-50)        /// </summary>        /// <returns></returns>        private string GetRecordRegion()        {            if (this.PageCount == 1) //只有一页            {                return "1-" + this.TotalCount.ToString();            }            else  //有多页            {                if(this.CurrentPage==1) //当前显示为第一页                {                    return "1-"+this.PageSize;                }                else if(this.CurrentPage==this.PageCount) //当前显示为最后一页                {                    return ((this.CurrentPage-1)*this.PageSize+1) +"-"+this.TotalCount;                }                else //中间页                {                    return ((this.CurrentPage-1) * this.PageSize+1)   + "-" + 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==1)            {                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==0)            {                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 = 1;            this.Bind();        }         private void btnPrev_Click(object sender, EventArgs e)        {            this.CurrentPage -= 1;                        this.Bind();        }         private void btnNext_Click(object sender, EventArgs e)        {            this.CurrentPage += 1;            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 = 1;    this.paging1.Location = new System.Drawing.Point(3, 347);    this.paging1.Name = "paging1";    this.paging1.PageCount = 0;    this.paging1.PageSize = 50;    this.paging1.Size = new System.Drawing.Size(512, 30);    this.paging1.TabIndex = 8; this.paging1.TotalCount = 0; //在这里注册事件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(255, 255, 255);//第一行               dgv.AlternatingRowsDefaultCellStyle.BackColor = Color.FromArgb(231, 232, 239);//第二行               dgv.GridColor = Color.FromArgb(207, 208, 216);//            dgv.RowTemplate.Height = 25;//列宽            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 = 100;                //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;        }

来自:http://www.cnblogs.com/markli/p/3863173.html
0 0
原创粉丝点击