WinForm轻松实现自定义分页

以前都是做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
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Winform中绘制自定义角度椭圆,可以利用C#语言中的System.Drawing命名空间中的Graphics类的方法来实现。首先,我们可以在Winform窗体的Paint事件中编写绘制椭圆的代码。在该事件中,我们可以创建一个Graphics对象,并通过其方法来绘制自定义角度的椭圆。 首先,我们可以创建一个Pen对象,用于定义绘制椭圆的边框颜色和宽度。然后,我们可以创建一个Rectangle对象,用于定义椭圆的位置和大小。接下来,我们可以使用Graphics对象的DrawEllipse方法来绘制椭圆,其中可以通过指定角度来绘制自定义角度椭圆。 例如,我们可以通过Graphics对象的RotateTransform方法来实现对椭圆进行旋转,从而绘制自定义角度的椭圆。通过指定旋转角度和旋转点的坐标,我们可以实现对椭圆的旋转,从而实现自定义角度的绘制。 另外,我们也可以通过Graphics对象的TranslateTransform方法来实现对椭圆的平移,从而调整椭圆的位置。通过指定平移的距离和方向,我们可以实现对椭圆的位置调整,从而实现自定义角度的绘制。 综上所述,通过在Winform的Paint事件中利用C#语言中的System.Drawing命名空间中的Graphics类的方法,我们可以实现绘制自定义角度椭圆的功能。利用旋转和平移等方式,我们可以实现对椭圆的角度和位置的自定义调整,从而实现自定义角度椭圆的绘制。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值