工作需要,要实现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不能刷新,看不到分页效果!
新闻热点
疑难解答