winform中DataGridView实现分页功能

WinForm轻松实现自定义分页 (转载)

WinForm轻松实现自定义分页 (转载)

 

转载至http://xuzhihong1987.blog.163.com/blog/static/267315872011315114240140/

以前都是做web开发,最近接触了下WinForm,发现WinForm分页控件好像都没有,网上搜索了一下,发现有很多网友写的分页控件,分页效果应该都能实现吧,只是其风格都不是很符合我想要的。做web的时候,我习惯了Extjs的Grid分页效果,所以也想在WinForm中做个类似的效果,所以咬咬牙,做个山寨版本的吧,虽然自己写费时费力,在项目进度考虑中不是很可取,但是还是特别想山寨一回,做自己喜欢的风格。

按照惯例,还是先看看实现效果图吧(有图有真像,才好继续下文呀)

winform中DataGridView实现分页功能

应用效果:(效果有点难看,因为我是刚装的

xp系统,还是经典主题,如果换成Win7系统或其他主题,效果还是会很不错的)

winform中DataGridView实现分页功能

我们要做的就是上图显示的一个自定义控件,这个效果参考自我做

web开发使用的Extjs之Grid的分页效果(如下图)

winform中DataGridView实现分页功能

Extjs的动画效果我们暂时就不实现了,这里只做个外观看起来想像即可,完全一样就脱离“山寨”概念了,总要比人家差点吧,谁让咱是模仿呢!

言归正传,我们现在就看看具体怎么实现吧:

第一步:先布局

    注:我们创建的是用户自定义控件,而不是WinForm窗体

winform中DataGridView实现分页功能

就是先做出个显示效果,这个布局很简单,在这就不多说,重点就是“首页、前一页、后一页、末页”图标,每个图标分两种,一是能点击的高亮效果,一个是灰色不不能点击。以下是套图:(大家如果不喜欢,可以去做成自己喜欢的风格图片)

winform中DataGridView实现分页功能

第二步:编写分页代码

   布局好了,那么第二步我们就要代码实现正确显示文字信息,分页事件,每页条数选择事件,公开属性和事件。以下是完整代码:

 /// <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);

加完后就能看到效果了,相当于托了一个分页控件的效果:(如下图所示)

winform中DataGridView实现分页功能

最后在事件中加入分页事件需要执行的代码:

winform中DataGridView实现分页功能
  1  /// <summary>
2
3 /// 分页事件
4
5 /// </summary>
6
7 /// <param name="e"></param>
8
9 private void paging1_EventPaging(EventArgs e)
10
11 {
12
13 GvDataBind(); //DataGridView数据绑定
14
15 }
16
17 /// <summary>
18
19 /// 查询
20
21 /// </summary>
22
23 /// <param name="sender"></param>
24
25 /// <param name="e"></param>
26
27 private void btnQuery_Click(object sender, EventArgs e)
28
29 {
30
31 paging1_EventPaging(e);
32
33 }
34
35 /// <summary>
36
37 /// gvOperateLogList 数据邦定
38
39 /// </summary>
40
41 private void GvDataBind()
42
43 {
44
45 PagingCondition paging = new PagingCondition()
46
47 {
48
49 startIndex=paging1.CurrentPage,
50
51 pageSize = paging1.PageSize
52
53 };
54
55 MultiCondition condition = new MultiCondition();
56
57 condition.DateSign="FOperateTime";
58
59 condition.BeginDate = dtBegin.Value;
60
61 condition.EndDate = dtEnd.Value;
62
63 if (comboOperator.Text != "")
64
65 {
66
67 condition.Dict.Add("FOperator", comboOperator.Text);
68
69 }
70
71 if (comboType.Text != "")
72
73 {
74
75 condition.Dict.Add("FType", comboType.Text);
76
77 }
78
79 if (comboObject.Text != "")
80
81 {
82
83 condition.Dict.Add("FOptObject", comboObject.Text);
84
85 }
86
87 if (txtBoxContent.Text != "")
88
89 {
90
91 condition.Dict.Add("FContent", txtBoxContent.Text);
92
93 }
94
95 DataTable dt = GetByCondition(paging, condition);
96
97 paging1.TotalCount = Convert.ToInt32(dt.TableName);
98
99 gvOperateLogList.DataSource = dt;
100
101 gvOperateLogList.Columns.Clear();
102
103 var dict = GetGvColumnsDict();
104
105 DataGridViewHelp.DisplayColList(gvOperateLogList, dict);
106
107 }
winform中DataGridView实现分页功能

注: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/

其他:

winform中DataGridView实现分页功能
 1  /// <summary>
2
3 /// gv显示列设置
4
5 /// </summary>
6
7 /// <returns></returns>
8
9 public Dictionary<string, string> GetGvColumnsDict()
10
11 {
12
13 Dictionary<string, string> dict = new Dictionary<string, string>();
14
15 dict.Add("FTYPE", "操作类型");
16
17 dict.Add("FOPTOBJECT", "操作对象");
18
19 dict.Add("FCONTENT", "操作内容");
20
21 dict.Add("FOperator", "操作人员");
22
23 return dict;
24
25 }
26
27
28
29 DataGridViewHelp.DisplayColList是一个静态方法,为一个辅助类:
30
31 /// <summary>
32
33 /// 替换列表
34
35 /// </summary>
36
37 /// <param name="dgv">类表名称</param>
38
39 /// <param name="dic">数据</param>
40
41 /// <param name="isRM">是否显示序列号</param>
42
43 public static void DisplayColList(DataGridView dgv, Dictionary<string, string> dic)//, bool isRM
44
45 {
46
47 _dgv = dgv;
48
49 dgv.RowsDefaultCellStyle.BackColor = Color.FromArgb(255, 255, 255);//第一行
50
51 dgv.AlternatingRowsDefaultCellStyle.BackColor = Color.FromArgb(231, 232, 239);//第二行
52
53 dgv.GridColor = Color.FromArgb(207, 208, 216);//
54
55 dgv.RowTemplate.Height = 25;//列宽
56
57 dgv.AllowUserToAddRows=false;//无空行
58
59 dgv.CellBorderStyle = DataGridViewCellBorderStyle.SingleVertical;
60
61 dgv.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
62
63 dgv.AllowUserToOrderColumns = true;
64
65 dgv.RowPostPaint += new DataGridViewRowPostPaintEventHandler(dgv_RowPostPaint);
66
67 dgv.CellPainting += new DataGridViewCellPaintingEventHandler(dgv_CellPainting);//列头样式
68
69 dgv.CellFormatting += new DataGridViewCellFormattingEventHandler(dgv_CellFormatting);//选中行样式
70
71
72
73 foreach (KeyValuePair<string, string> cl in dic)
74
75 {
76
77 dgv.AutoGenerateColumns = false;
78
79 DataGridViewTextBoxColumn obj = new DataGridViewTextBoxColumn();
80
81 obj.DataPropertyName = cl.Key;
82
83 obj.HeaderText = cl.Value;
84
85 obj.Name = cl.Key;
86
87 obj.Width = 100;
88
89 //obj.DefaultCellStyle.Padding.All = 10;
90
91 obj.Resizable = DataGridViewTriState.True;
92
93 dgv.Columns.AddRange(new DataGridViewColumn[] { obj });
94
95 }
96
97 }
98
99
winform中DataGridView实现分页功能

到此实现就全部完成了,运行效果后就是前面所示的效果!也可以动态修改每页条数。

winform中DataGridView实现分页功能

说在最后,改功能简单是简单,但是涉及到很多知识点,委托、事件、

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;
}

==========================================================================

C#开发WinForm分页控件

闲暇之余,自己动手做了个分页控件,真是受益良多

WinFormPager.dll控件下载地址 WinFormPager源代码下载地址

以下是调用分页控件WinFormPager方法

//第一步:指定返回的记录数

winFormPager1.RecordCount = 返回记录数;

//第二步:在控件的PageChanged事件中执行绑定DataGridView的方法

private void winFormPager1_PageChanged()
 {
     dataGridView1.DataSource = GetList(winFormPager1.PageSize,winFormPager1.CurrentPage);//GetList为获取数据库记录方法,不介绍
 }

//注:完成以上步骤就可成功调用,其余PageSize属性等可在属性浏览器中设置

以下是分页控件WinformPager完整代码:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using DevComponents.DotNetBar;

namespace WinFormPager
{
    public partial class WinFormPager : UserControl
    {
        int currentPage = 1;//当前页 
        /// <summary>
        /// 当前页 
        /// </summary>
        [Description("当前页"), Category("分页设置")]
        public int CurrentPage
        {
            get { return currentPage; }
            set { currentPage = value; }
        }
        int pageSize = 10;//每页显示条数
        /// <summary>
        /// 每页显示条数
        /// </summary>
        [Description("每页显示条数"), Category("分页设置")] 
        public int PageSize
        {
            get { return pageSize; }
            set { pageSize = value; }
        }
        int pageTotal = 0;//总共多少页 
        /// <summary>
        /// 总共多少页 
        /// </summary>
        [Description("总共多少页"), Category("分页设置")] 
        public int PageTotal
        {
            get { return pageTotal; }
            set { pageTotal = value; }
        }
        int currentGroup = 1;//当前组
        /// <summary>
        /// 当前组
        /// </summary>
        [Description("当前组"), Category("分页设置")] 
        public int CurrentGroup
        {
            get { return currentGroup; }
            set { currentGroup = value; }
        }
        int groupSize = 10;//每组显示页数
        /// <summary>
        /// 每组显示页数
        /// </summary>
        [Description("每组显示页数"), Category("分页设置")] 
        public int GroupSize
        {
            get { return groupSize; }
            set { groupSize = value; }
        }
        int groupTotal = 0;//总共多少组
        /// <summary>
        /// 总共多少组
        /// </summary>
        [Description("总共多少组"), Category("分页设置")]  
        public int GroupTotal
        {
            get { return groupTotal; }
            set { groupTotal = value; }
        }
        /// <summary>
        /// 总的记录数
        /// </summary>
        private int recordCount;//总的记录数
        [Description("总的记录数"), Category("分页设置")] 
        public int RecordCount
        {
            get { return recordCount; }
            set 
            {
                recordCount = value;
                InitData();// 初始化数据
                PageChanged();//当前页改变事件
            }
        }
        private int buttonWidth = 20;//按钮宽度
        /// <summary>
        /// 按钮宽度
        /// </summary>
        [Description("按钮宽度"), Category("分页设置")] 
        public int ButtonWidth
        {
            get { return buttonWidth; }
            set { buttonWidth = value; }
        }
        private int buttonHeight = 23;//按钮高度
        /// <summary>
        /// 按钮高度
        /// </summary>
        [Description("按钮高度"), Category("分页设置")] 
        public int ButtonHeight
        {
            get { return buttonHeight; }
            set { buttonHeight = value; }
        }
        private int buttonDistance = 0;//按钮间距离
        /// <summary>
        /// 按钮间距离
        /// </summary>
        [Description("按钮间距离"), Category("分页设置")] 
        public int ButtonDistance
        {
            get { return buttonDistance; }
            set { buttonDistance = value; }
        }
        List<Control> listControl = new List<Control>();//分页的按钮集合

public delegate void PageChangeDelegate();
        /// <summary>
        /// 当前页改变时发生的事件
        /// </summary>
        [Description("当前页改变时发生的事件"), Category("分页设置")]
        public event PageChangeDelegate PageChanged;
        public WinFormPager()
        {
            InitializeComponent();
            PageChanged = SetBtnPrePageAndBtnNextPage;
            PageChanged();
        }
        /// <summary>
        /// 初始化数据
        /// </summary>
        private void InitData() 
        {
            PageTotal = RecordCount / PageSize;//总共多少页            
            if (RecordCount % PageSize != 0)
            {
                PageTotal++;
            }
            GroupTotal = PageTotal / GroupSize;//总共多少组
            if (PageTotal % GroupSize != 0)
            {
                GroupTotal++;
            }
            for (int i = 0; i < PageTotal; i++)
            {
                cmbPage.Items.Add((i + 1).ToString());//添加下拉框值
            }
            BuildPageControl();//创建分页数字按钮       
        }
        /// <summary>
        /// 创建分页数字按钮
        /// </summary>
        private void BuildPageControl()
        {
            int x = 0;//按钮横坐标
            int y = 0;//按钮纵坐标
            int num = 0;//按钮数
            for (int i = GroupSize * (CurrentGroup - 1); i < GroupSize * CurrentGroup; i++)
            {
                if (i + 1 > PageTotal)
                {
                    break;
                }
                num++;
            }
            int xBtnPreGroup = x + (ButtonWidth + ButtonDistance) * num;//btnPerGroup横坐标
            //指定上一组 下一组 上一页 下一页 坐标 
            btnPreGroup.Location = new Point(xBtnPreGroup, y);
            btnNextGroup.Location = new Point(btnPreGroup.Location.X + btnPreGroup.Width + ButtonDistance, y);
            btnPrePage.Location = new Point(btnNextGroup.Location.X + btnNextGroup.Width + ButtonDistance, y);
            btnNextPage.Location = new Point(btnPrePage.Location.X + btnPrePage.Width + ButtonDistance, y);
            cmbPage.Location = new Point(btnNextPage.Location.X + btnNextPage.Width + ButtonDistance, y+(ButtonHeight-cmbPage.Height)/2);
            btnGo.Location = new Point(cmbPage.Location.X + cmbPage.Width + ButtonDistance, y);
            //设置整个控件的宽度、高度
            this.Width = btnGo.Location.X + btnGo.Width;
            this.Height = ButtonHeight;
            btnPreGroup.Height = ButtonHeight;
            btnNextGroup.Height = ButtonHeight;
            btnPrePage.Height = ButtonHeight;
            btnNextPage.Height = ButtonHeight;
            cmbPage.Height = ButtonHeight;
            btnGo.Height = ButtonHeight;
            //循环遍历移除控件
            foreach (Control c in listControl)
            {
                this.Controls.Remove(c);
            }
            listControl = new List<Control>();
            ButtonX button = null;
            //循环创建控件
            for (int i = GroupSize * (currentGroup - 1); i < GroupSize * CurrentGroup; i++)
            {
                if (i + 1 > PageTotal)
                {
                    break;
                }
                button = new ButtonX();
                button.Text = (i + 1).ToString();
                button.Width = ButtonWidth;
                button.Height = ButtonHeight;
                button.ColorTable = DevComponents.DotNetBar.eButtonColor.OrangeWithBackground;
                button.Location = new Point(x, y);
                button.Click += new EventHandler(button_Click);
                this.Controls.Add(button);
                button.BringToFront();
                listControl.Add(button);//添加进分页按钮的集合
                x += ButtonWidth + ButtonDistance;
            }
            //上一组是否可用
            if (CurrentGroup == 1)
            {
                btnPreGroup.Enabled = false;
            }
            else
            {
                btnPreGroup.Enabled = true;
            }
            //下一组是否可用
            if (CurrentGroup == GroupTotal)
            {
                btnNextGroup.Enabled = false;
            }
            else
            {
                btnNextGroup.Enabled = true;
            }
        }
        /// <summary>
        /// 数字按钮分页
        /// </summary>
        private void button_Click(object sender, EventArgs e)
        {
            CurrentPage = int.Parse((sender as ButtonX).Text);
            PageChanged();
        }
        /// <summary>
        /// 设置上一页、下一页是否可用以及当前页按钮字体颜色
        /// </summary>
        private void SetBtnPrePageAndBtnNextPage() 
        {
            //上一页是否可用
            if (CurrentPage == 1)
            {
                btnPrePage.Enabled = false;
            }
            else
            {
                btnPrePage.Enabled = true;
            }
            //下一页是否可用
            if (CurrentPage == PageTotal)
            {
                btnNextPage.Enabled = false;
            }
            else
            {
                btnNextPage.Enabled = true;
            }
            //设置数字分页按钮文本颜色
            foreach (Control c in this.Controls)
            {
                //当前页字体为红色
                if (c.Text == CurrentPage.ToString() && c is ButtonX)
                {
                    c.ForeColor = Color.Red;
                }
                else
                {
                    c.ForeColor = Color.Blue;
                }
            }
        }
        /// <summary>
        /// 上一组
        /// </summary>
        private void btnPreGroup_Click(object sender, EventArgs e)
        {
            CurrentGroup--;
            BuildPageControl();
            CurrentPage = GroupSize * (CurrentGroup - 1) + 1; ;
            PageChanged();
        }
        /// <summary>
        /// 下一组
        /// </summary>
        private void btnNextGroup_Click(object sender, EventArgs e)
        {
            CurrentGroup++;
            BuildPageControl();
            CurrentPage = GroupSize * (CurrentGroup - 1) + 1; ;
            PageChanged();
        }
        /// <summary>
        /// 上一页
        /// </summary>
        private void btnPrePage_Click(object sender, EventArgs e)
        {
            //如果是当前组的第一页,直接上一组
            if (CurrentPage == GroupSize * (CurrentGroup - 1) + 1)
            {
                CurrentGroup--;
                BuildPageControl();
                CurrentPage --; ;
                PageChanged();
                return;
            }
            CurrentPage--;
            PageChanged();
        }
        /// <summary>
        /// 下一页
        /// </summary>
        private void btnNextPage_Click(object sender, EventArgs e)
        {
            //如果是当前组的最后一页,直接下一组
            if (CurrentPage == GroupSize * (CurrentGroup - 1) + GroupSize)
            {
                btnNextGroup_Click(null, null);
                return;
            }
            CurrentPage++;
            PageChanged();
        }
        /// <summary>
        /// 转到第几页
        /// </summary>
        private void btnGo_Click(object sender, EventArgs e)
        {
            try
            {
                CurrentPage = int.Parse(cmbPage.Text);
                PageChanged();
            }
            catch
            {
                MessageBox.Show("请输入数字");
            }
        }
    }
}

===============================================================================

http://liyaguang20111105.blog.163.com/blog/static/19929420220146283255809/

在winform的设计中,要实现对DataGridView控件的分页功能,需要两个控件:BindingSource、BindingNavigator,根据需求可对BindingNavigator进行*的扩展,下图的示例则是根据一般需求对分页功能的实现。红色区域是对BindingNavigator控件扩展后的效果。

 
winform中DataGridView实现分页功能
 

具体实现过程 :

//窗体构造方法中定义分页所需变量:

int pageSize = 0;     //每页显示行数

int nMax = 0;         //总记录数

int pageCount = 0;    //页数=总记录数/每页显示行数

int pageCurrent = 0;   //当前页号

int nCurrent = 0;      //当前记录行

DataTable dtInfo = new DataTable();  //存取查询数据结果

//分页功能实现

public void InitDataSet()

{

//判断每页显示记录数是否为空,在初始话窗体时为真

if (txtRecordNumOfPage.Text.Trim() == "")

{

try

{

//pageSize = Convert.ToInt16(ConfigurationManager.AppSettings["PageSize"]);      //设置页面行数

//读取配置文件中设置的每页显示条数

string szConfigFileName = Application.ExecutablePath + ".config";

XmlDocument doc = new XmlDocument();

doc.Load(szConfigFileName);

XmlNode root = doc.SelectSingleNode("configuration");

XmlNode node = root.SelectSingleNode("appSettings/add[@key='PageSize']");

XmlElement el = node as XmlElement;

pageSize = Convert.ToUInt16(el.GetAttribute("value"));

}

catch

{

}

if (pageSize == 0)

{

pageSize = 20;        //如果读取配置文件失败,则默认将每页显示条数设置为20

}

txtRecordNumOfPage.Text = pageSize.ToString();    //界面显示的“每页记录数”赋值

}

else

{

//读取界面设置的每页显示条数

pageSize = Convert.ToUInt16(txtRecordNumOfPage.Text.Trim());

}

//总记录数赋值

nMax = dtInfo.Rows.Count;

pageCount = (nMax / pageSize);    //采用整除计算页数

//判断整除后是否有余数,有则对页数进行+1

if ((nMax % pageSize) > 0) pageCount++;

pageCurrent = 1;    //当前页数从1开始

nCurrent = 0;       //当前记录数从0开始

//调用显示数据方法

LoadData();

}

//显示数据方法

private void LoadData()

{

int nStartPos = 0;   //当前页面开始记录行

int nEndPos = 0;     //当前页面结束记录行

//判断查询结果是否为空

if (dtInfo.Rows.Count == 0)

{

dgvExperInfo.DataSource = null;

return;

}

else

{

DataTable dtTemp = dtInfo.Clone();   //克隆DataTable结构,即将字段名称进行复制

if (pageCurrent == 1)

{

bindingNavigatorMoveFirstPage.Enabled = false;

bindingNavigatorMovePreviousPage.Enabled = false;

}

else

{

bindingNavigatorMoveFirstPage.Enabled = true;

bindingNavigatorMovePreviousPage.Enabled = true;

}

if (pageCurrent == pageCount)

{

nEndPos = nMax;

bindingNavigatorMoveLastPage.Enabled = false;

bindingNavigatorMoveNextPage.Enabled = false;

}

else

{

bindingNavigatorMoveLastPage.Enabled = true;

bindingNavigatorMoveNextPage.Enabled = true;

nEndPos = pageSize * pageCurrent;

}

nStartPos = nCurrent;

lblPageCount.Text = pageCount.ToString();             //界面显示总页数

lblCurrentPage.Text = Convert.ToString(pageCurrent);//当前页数

txtCurrentPage.Text = Convert.ToString(pageCurrent);//跳转到页数的显示

//从元数据源复制记录行

for (int i = nStartPos; i < nEndPos; i++)

{

dtTemp.ImportRow(dtInfo.Rows[i]);

nCurrent++;

}

bdsInfo.DataSource = dtTemp;

bdnInfo.BindingSource = bdsInfo;

dgvExperInfo.DataSource = bdsInfo;

dgvExperInfo.ClearSelection();

}

}

//BindingNavigator控件上的项目点击事件,通过配置各个Item的Text值进行判断执行

private void bdnInfo_ItemClicked(object sender, ToolStripItemClickedEventArgs e)

{

if (e.ClickedItem.Text == "上一页")

{

pageCurrent--;

if (pageCurrent <= 0)

{

MessageBox.Show("已经是第一页,请点击“下一页”查看!");

pageCurrent++;

return;

}

else

{

nCurrent = pageSize * (pageCurrent - 1);

}

LoadData();

}

if (e.ClickedItem.Text == "下一页")

{

pageCurrent++;

if (pageCurrent > pageCount)

{

MessageBox.Show("已经是最后一页,请点击“上一页”查看!");

pageCurrent--;

return;

}

else

{

nCurrent=pageSize*(pageCurrent-1);

}

LoadData();

}

if (e.ClickedItem.Text == "首页")

{

pageCurrent = 1;

nCurrent = 0;

LoadData();

}

if (e.ClickedItem.Text == "尾页")

{

pageCurrent = pageCount;

nCurrent = pageSize * (pageCurrent - 1);

LoadData();

}

}

//跳转页实现

private void btnPage_Click(object sender, EventArgs e)

{

if (txtCurrentPage.Text.Trim() != "")

{

pageCurrent = Convert.ToInt16(txtCurrentPage.Text.Trim());

//若输入页号大于最大显示页号,则跳转至最大页

if (pageCurrent > pageCount)

{

pageCurrent = pageCount;

nCurrent = pageSize * (pageCurrent - 1);

}

//若输入页号小于1,则跳转至第一页

else if (pageCurrent < 1)

{

pageCurrent = 1;

nCurrent = 0;

LoadData();

}

//跳转至输入页号

else

{

nCurrent = pageSize * (pageCurrent - 1);            //当前行数定位

}

//调用加载数据方法

LoadData();

}

}

//当前页输入字符限制

private void txtCurrentPage_TextChanged(object sender, EventArgs e)

{

bool IsNum = true;

foreach (char c in txtCurrentPage.Text.Trim())

{

if (!char.IsNumber(c)) { IsNum = false; break; }

}

if (IsNum == false)

{

txtCurrentPage.Text = pageCurrent.ToString();

}

}

//当前页回车事件调用跳转页的操作

private void txtCurrentPage_KeyPress(object sender, KeyPressEventArgs e)

{

if (e.KeyChar == 13)

{

btnPage_Click(sender,e);

}

}

//每页显示记录数变更事件

private void txtRecordNumOfPage_TextChanged(object sender, EventArgs e)

{

bool IsNum = true;

//输入字符限制

foreach (char c in txtRecordNumOfPage.Text.Trim())

{

if (!char.IsNumber(c)) { IsNum = false; break; }

}

if (IsNum == false)

{

txtRecordNumOfPage.Text = pageSize.ToString();

}

//判断输入的每页显示条数是否为空或是否为0,输入长度是否大于4位等情况

if (txtRecordNumOfPage.Text.Trim() == "" || Convert.ToUInt32(txtRecordNumOfPage.Text.Trim()) == 0 || txtRecordNumOfPage.Text.Trim().Length > 4)

{

txtRecordNumOfPage.Text = pageSize.ToString();

}

//规避了特殊情况后直接调用显示数据方法

LoadDocInfoToDGV();

}

        至此,winform中对DataGridView控件的分页功能已经实现,该方法是在网上查了相关资料后参照一些常用的分页效果进行了一些扩展,也在组长的要求下,完善了一些细节上的工作:由于屏幕分辨率的不同,用户可自行对每页显示条数进行设置,设置结果可以在关闭窗体的事件中保存至配置文件,下次进行默认读取;对分页控件中按钮操作的优化,判断是否能够使用的功能,代码中已经进行了体现;另外由于显示器分辨率不尽相同,需要在窗体加载时,设置控件显示的位置,也同样需要代码进行控制。
        需要注意的一点是该分页效果达到的是真分页的功能,要想实现假分页的效果还要进行一些改动。可见实现分页的效果还是要考虑很多方面的,但真正实现后的效果还是很实用的。
 
====================================================================
 C# Code 
 
C# WinForm中DataGirdView简单分页功能
1.定义变量
  
int pageSize = 0; //每页显示行数
int nMax = 0; //总记录数
int pageCount = 0; //页数=总记录数/每页显示行数
int pageCurrent = 0; //当前页号
int nCurrent = 0; //当前记录行
PS (在bdnInfo中添加上一页, 下一页, lblPageCountText, txtCurrentPage.Text)
2.在窗体内分别添加BindingNavigator (bdnInfo), BindingSource (bdsInfo), DataGirdView1 (dgvInfo)
3.绑定dgvInfo数据
DataSet ds = new DataSet();
ds = userBLL.GetModel();
DaTaTable dt = new DaTaTable ();
dt = ds.Tables[0];
this.dgvInfo.DataSource = dt;
InitDataSet();

4.初始化dgvInfo
private void InitDataSet()
{
    pageSize = 10; //设置页面行数
    nMax = dt.Rows.Count;
    pageCount = (nMax / pageSize); //计算出总页数
    if ( (nMax % pageSize) > 0)
    {
        pageCount++;
    }
    pageCurrent = 1; //当前页数从1开始
    nCurrent = 0; //当前记录数从0开始
    LoadData();
}

5.加载数据
private void LoadData()
{
    int nStartPos = 0; //当前页面开始记录行
    int nEndPos = 0; //当前页面结束记录行
    System.Data.DataTable dtTemp = dt.Clone(); //克隆DataTable结构框架
    if (dtTemp != null || dtTemp.Rows.Count > 0)
    {
        if (pageCurrent == pageCount)
        {
            nEndPos = nMax;
        }
        else
        {
            nEndPos = pageSize * pageCurrent;
        }
        nStartPos = nCurrent;
        lblPageCount.Text = pageCount.ToString();//在bdnInfo中添加lable记录总页数
        txtCurrentPage.Text = Convert.ToString (pageCurrent); //在bdnInfo中添加Textbox记录当前页数
        //从元数据源复制记录行
        for (int i = nStartPos; i < nEndPos; i++)
        {
            if (i < dt.Rows.Count)
            {
                dtTemp.ImportRow (dt.Rows[i]);
                nCurrent++;
            }
        }
        bdsInfo.DataSource = dtTemp;
        bdnInfo.BindingSource = bdsInfo;
        dgvInfo.DataSource = bdsInfo;
    }
    else
    {
        return;
    }
}

6.在bdnInfo的ItemClicked事件中添加代码
private void bdnInfo_ItemClicked (object sender, ToolStripItemClickedEventArgs e)
{
    if (e.ClickedItem.Text == "上一页")
    {
        pageCurrent--;
        if (pageCurrent <= 0)
        {
            MessageBox.Show ("已经是第一页,请点击“下一页”查看!");
            return;
        }
        else
        {
            if (pageCurrent > pageSize)
            {
                pageCurrent = Convert.ToInt32 (lblPageCount.Text);
            }
            else if (pageCurrent > Convert.ToInt32 (lblPageCount.Text) )
            {
                pageCurrent = Convert.ToInt32 (lblPageCount.Text);
            }
            nCurrent = pageSize * (pageCurrent - 1);
        }
        LoadData();
    }
    if (e.ClickedItem.Text == "下一页")
    {
        if (pageCurrent <= 0)
        {
            pageCurrent = 1;
        }
        pageCurrent++;
        if (pageCurrent > pageCount)
        {
            MessageBox.Show ("已经是最后一页,请点击“上一页”查看!");
            return;
        }
        else
        {
            nCurrent = pageSize * (pageCurrent - 1);
            if (nCurrent <= 0)
            {
                return;
            }
        }
        LoadData();
    }
}

上一篇:《R数据挖掘入门》彩色插图(第8章)


下一篇:RotateAnimation详解