分享
 
 
 

现windows应用程序中用的datagrid具有分页功能

王朝system·作者佚名  2006-01-31
窄屏简体版  字體: |||超大  

工作需要,要实现windows应用程序中用的datagrid具有分页功能,不知道ms怎么想的,asp.net的datagrid有这样的功能,为什么不在winForm的datagrid里面提供这样的功能,还得让我费这么大劲儿来重写这个控件,真是麻烦。

首先,我们要做一个类来继承系统的datagrid:

using System;

using System.Drawing;

using System.Collections;

using System.ComponentModel;

using System.Windows.Forms;

using System.Data;

namespace oilx.PagingDataGrid

{

public class PagingDataGrid : DataGrid

{

// 声明一些必要的全局变量。

private System.ComponentModel.Container components = null;

/// <summary>

///

/// </summary>

private const int MarkerWith = 14;

/// <summary>

///

/// </summary>

private Point _pointTopLeft;

/// <summary>

///

/// </summary>

private int _row = 1;

//

private int _rowNumberFigure = 0;

private bool _zeroPadding = false;

/// <summary>

///

/// </summary>

private string _rowHeaderCaption = String.Empty;

/// <summary>

///

/// </summary>

private int _pageSize = 10;

/// <summary>

///

/// </summary>

private int _currentPageCount = 1;

/// <summary>

///

/// </summary>

private bool _allowPaging = false;

/// <summary>

///

/// </summary>

private int _previousPageCount = -1;

/// <summary>

///

/// </summary>

private DataTable _pageDataSource;

/// <summary>

///构造函数

/// </summary>

/// <param name="container"></param>

public PagingDataGrid (System.ComponentModel.IContainer container)

{

container.Add(this);

InitializeComponent();

InitiarizeControl();

}

/// <summary>

///构造函数重载

/// </summary>

public FixdItemDataGrid()

{

InitializeComponent();

InitiarizeControl();

}

// 下面我们需要增加一些用于分页的公共属性

/// <summary>

/// 页面大小,即每页现实的数据条数

/// </summary>

[Browsable(true),Description("页面大小")]

public int PageSize

{

get

{

return _pageSize;

}

set

{

_pageSize = value;

}

}

/// <summary>

/// 分页数

/// </summary>

[Browsable(true),Description("分页数")]

public int PageCount

{

get

{

if(DataSource == null)

{

return 0;

}

if(_pageDataSource == null || _pageDataSource.Rows.Count <= 0)

{

return 0;

}

int i = _pageDataSource.Rows.Count%PageSize==0?0:1;

return _pageDataSource.Rows.Count/PageSize+i;

}

}

/// <summary>

/// 当前页数

/// </summary>

[Browsable(true),Description("当前页数")]

public int CurrentPageCount

{

get

{

if(_currentPageCount < 0)

{

return 1;

}

if(_currentPageCount >= PageCount)

{

return PageCount;

}

return _currentPageCount;

}

set

{

if(value >=PageCount)

{

_currentPageCount = PageCount;

}

_currentPageCount = value;

}

}

/// <summary>

///是否允许分页

/// </summary>

[Browsable(true),Description("是否允许分页")]

public bool AllowPaging

{

get

{

return _allowPaging;

}

set

{

_allowPaging = value;

}

}

/// <summary>

///行标题

/// </summary>

[Browsable(true),Description("行标题")]

public string RowHeaderCaption

{

get

{

return _rowHeaderCaption;

}

set

{

_rowHeaderCaption = value;

}

}

// 基本工作都作完了,下面开始我们分页的重点,go!

// 我们需要重写系统一个方法,那就是:

/// <summary>

/// 该方法在数据源被修改的时候激活。

/// </summary>

/// <param name="e"></param>

protected override void OnDataSourceChanged(System.EventArgs e)

{

base.OnDataSourceChanged(e);

// 如果数据源为空那么就返回。

if( this.DataSource == null )

{

return;

}

// 下面判断数据源的类型,一般情况下,datagrid数据源形式为3种,1,dataset,2,datatable,3,dataview。

// 在这里我们要做的是把数据源的数据保存到另外一个变量里面,这样当我们在作分页

//的时候,需要修改数据源时,可以把这个变量当作原始的数据源来进行判断。

if(this.DataSource is DataSet)

{

if( ((DataSet)DataSource).Tables.Count > 0)

{

this.DataSource = ((DataSet)DataSource).Tables[0];

}

else

{

return;

}

}

if(_pageDataSource == null)

{

if(DataSource is DataSet)

{

if(((DataSet)DataSource).Tables[0].Rows.Count <=0)

{

return;

}

_pageDataSource = ((DataSet)DataSource).Tables[0].Clone();

for(int i = 0;i<((DataSet)DataSource).Tables[0].Rows.Count;i++)

{

DataRow drRow = _pageDataSource.NewRow();

drRow.ItemArray = ((DataSet)DataSource).Tables[0].Rows[i].ItemArray;

_pageDataSource.Rows.Add(drRow);

}

}

else if(DataSource is DataTable)

{

if(((DataTable)DataSource).Rows.Count <= 0)

{

return;

}

_pageDataSource = ((DataTable)DataSource).Clone();

for(int i = 0;i<((DataTable)DataSource).Rows.Count;i++)

{

DataRow drRow = _pageDataSource.NewRow();

drRow.ItemArray = ((DataTable)DataSource).Rows[i].ItemArray;

_pageDataSource.Rows.Add(drRow);

}

}

else if(DataSource is DataView)

{

if( ((DataView)DataSource).Table.Rows.Count <= 0)

{

return;

}

_pageDataSource = ((DataView)DataSource).Table.Clone();

for(int i = 0;i<((DataView)DataSource).Table.Rows.Count;i++)

{

DataRow drRow = _pageDataSource.NewRow();

drRow.ItemArray = ((DataView)DataSource).Table.Rows[i].ItemArray;

_pageDataSource.Rows.Add(drRow);

}

}

}

_pointTopLeft = new Point(this.GetCellBounds(0,0).X + 4, this.GetCellBounds(0,0).Y + 4);

}

// 上面的所作的只是把原数据源数据导入到_pageDataSource这个datatable里面,在这里有

//人可能要问为什么不用 _pageDataSource = (DataTable)this.DataSource;

// 而使用

//DataRow drRow = _pageDataSource.NewRow();

//drRow.ItemArray = ((DataView)DataSource).Table.Rows[i].ItemArray;

//_pageDataSource.Rows.Add(drRow);

//这是因为DataTable是引用类型,如果直接付值的话,那么当原数据源的数据被修改时,——//_pageDataSource也会被修改。

//好了,临时数据已经处理完了,那么真正的分页处理开始,大家都知道,.net控件要显示在窗体//上,那么需要我们把它的实体画上去,那么ms.net在所有控件都提供了下面这样的方法,可以//让我们把控件按照我们修改后的形式表现出来:

/// <summary>

///

/// </summary>

/// <param name="e"></param>

protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)

{

base.OnPaint(e);

if( this.DataSource == null )

{

return;

}

if(DataSource != null && DataSource is DataSet)

{

return;

}

// 在这里我们开始对分页进行进行处理

if(AllowPaging)

{

if(_pageDataSource != null)

{

if(_previousPageCount != CurrentPageCount)

{

// 判断当前是第几页

int i = CurrentPageCount*PageSize-PageSize;

if(i<0)

{

i = 0;

}

//下面判断是否为最后一页

if(i <= _pageDataSource.Rows.Count)

{

DataTable dtPage = _pageDataSource.Clone();

int iCount = 0;

根据PageSize来生成一个dataTable,重新进行数据源绑定。

for(;i<_pageDataSource.Rows.Count;i++)

{

DataRow drRow = dtPage.NewRow();

drRow.ItemArray= _pageDataSource.Rows[i].ItemArray;

dtPage.Rows.Add(drRow);

iCount ++;

if(iCount>=PageSize)

{

break;

}

}

// 绑定新的数据源

this.DataSource = dtPage;

}

_previousPageCount = CurrentPageCount;

}

}

}

// RowHeaders如果为true,那么我们要给RowHeader上面标上序号和标题

if(this.RowHeadersVisible)

{

DataGrid.HitTestInfo hti = this.HitTest(_pointTopLeft);

int iRowhti = hti.Row;

if(iRowhti < 0)

{

iRowhti = 0;

}

int iDelta = this.GetCellBounds(iRowhti, 0).Height + 1;

int iHeight = this.GetCellBounds(iRowhti, 0).Top + 1;

// 这个方法里面是显示RowHeaders的标题,详见该方法实现

ShowColumnTitles(e);

CurrencyManager cm = (CurrencyManager) this.BindingContext[this.DataSource, this.DataMember];

while(iHeight < this.Height - iDelta && iRowhti < cm.Count)

{

string strText = String.Empty;

if(_zeroPadding)

{

strText = String.Format("{0}", _row + iRowhti).PadLeft(_rowNumberFigure, '0');

}

else

{

strText = String.Format("{0}", _row + iRowhti);

}

e.Graphics.DrawString(strText, this.Font, new SolidBrush(Color.Black), 20, iHeight);

// 下面处理的是在RowHeaders上面画一条分割线,为了有阴影的感觉,我画了一条灰色和白色两条,看着还挺像 ^_^

if(!this.CaptionVisible)

{

ShowSepalatorLine(e, new Point(17, 2), new Point(17, iHeight-2 + this.PreferredRowHeight),Color.Gray);

ShowSepalatorLine(e, new Point(18, 2), new Point(18, iHeight-2 + this.PreferredRowHeight),Color.White);

}

else

{

ShowSepalatorLine(e, new Point(17, 20), new Point(17, iHeight-2 + this.PreferredRowHeight),Color.Gray);

ShowSepalatorLine(e, new Point(18, 20), new Point(18, iHeight-2 + this.PreferredRowHeight),Color.White);

}

iHeight += iDelta;

iRowhti++;

}

_row =CurrentPageCount*PageSize-PageSize+1;

if(_row < 0)

{

_row =1;

}

}

}

// 画线

private void ShowSepalatorLine(PaintEventArgs e, Point ptStart, Point ptEnd,Color lineColor)

{

Pen pen = new Pen(new SolidBrush(lineColor), 1);

e.Graphics.DrawLine(pen, ptStart, ptEnd);

}

/// <summary>

/// 显示RowHeaders的标题

/// </summary>

/// <param name="e"></param>

/// <param name="source"></param>

private void ShowColumnTitles(PaintEventArgs e)

{

string strHeader = RowHeaderCaption;

int iX = MarkerWith + 5;

int iWith = this.RowHeaderWidth;

using(StringFormat sf = new StringFormat())

{

sf.FormatFlags = StringFormatFlags.NoWrap;

sf.Trimming = StringTrimming.EllipsisCharacter;

sf.Alignment = StringAlignment.Near;

sf.LineAlignment = StringAlignment.Center;

RectangleF rect;

if(!CaptionVisible)

{

rect = new RectangleF(new PointF(iX, 3), new SizeF(iWith, this.PreferredRowHeight));

}

else

{

rect = new RectangleF(new PointF(iX, 20), new SizeF(iWith, this.PreferredRowHeight));

}

e.Graphics.DrawString(strHeader, this.Font, new SolidBrush(Color.Black), rect, sf);

}

}

/// <summary>

/// ?}?E?X?|?C?“?^‚???“®¸?—¯

/// </summary>

/// <param name="e"></param>

protected override void OnMouseMove(System.Windows.Forms.MouseEventArgs e)

{

DataGrid.HitTestInfo hitTestInfo = this.HitTest(new Point(e.X, e.Y)) if(hitTestInfo.Type == DataGrid.HitTestType.RowResize)

{

return;

}

base.OnMouseMove(e);

}

/// <summary>

///

/// </summary>

/// <param name="e"></param>

protected override void OnMouseDown(System.Windows.Forms.MouseEventArgs e)

{

DataGrid.HitTestInfo hitTestInfo = this.HitTest(new Point(e.X, e.Y));

if(hitTestInfo.Type == DataGrid.HitTestType.RowResize)

{

return;

}

base.OnMouseDown(e);

}

}

}

好了,到这里这个,这个分页的datagrid就算完了。

程序实现:

dataGrid1.CurrentPageCount ++;

dataGrid1.Invalidate();

一定要写dataGrid1.Invalidate();这个方法,不然datagrid不能刷新,看不到分页效果!

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有