datagrid使用技巧(二)
------------如何实现多行表头
有时候听有些朋友抱怨.net的datagrid不是很好用。就我个人的体会,datagrid的功能非常强大,可以使我们随心所欲的完成各种各样的工作,可惜就是实现起来不够简单明了。我对平时经常碰到的一些问题积累了一些解决的方法,现在把它们总结一下供大家参考。
比较经常碰到的一个问题是:我们希望datagrid的表头是多行的(图1)。我在网上找了很久也找不到解决的方法,后来想到了datagrid的captiontext和captionfont属性。于是我就想能不能在caption的显示区域画出多行表头。下面的示例代码实现了这个想法,结果如图1所示。
首先需要编写一个类来表示自画的表头,这个类将记录表头的显示文本、图标和属于它管辖的列的信息。
//表头类
public class topheadercolumn
{
public topheadercolumn()
{
this.columncollection=new arraylist();
}
private string caption;
//表头的显示文本
public string caption
{
get {return caption;}
set {caption=value;}
}
private arraylist columncollection;
//用来记录属于表头管辖的各列的信息(通过往集合里添加object)
public arraylist columncollection
{
get {return this.columncollection;}
set {this.columncollection=value;}
}
private int width;
//表头的宽度
public int width
{
get {return width;}
set {width=value;}
}
private image image=null;
//表头的图标
public image image
{
get {return image;}
set {image=value;}
}
}
另外,因为以后的代码需要datagrid水平滚动条的位置,而datagrid无法取得水平滚动条的位置,所以需要对datagrid做一点修改。
public class mydatagrid:datagrid
{
public scrollbar hscrollbar
{
get {return this.horizscrollbar;}
}
}
好了,可以工作了。新建一个window应用程序,加入一个mydatagrid、sqlconnection和imagelist,连接sql数据库northwind。当然,还得加入上面的代码
namespace windowsapplication1
{
public class form1 : system.windows.forms.form
{
private system.data.sqlclient.sqlconnection sqlconnection1;
private mydatagrid datagrid1;
private arraylist al;
private system.windows.forms.imagelist imagelist1;
\\在initializecomponent()里加入这一句:this.datagrid1 = new mydatagrid(),并根据你的需要设置其他的datagrid属性。注意,captionvisible必须设为true,captiontext=""。
private void form1_load(object sender, system.eventargs e)
{
sqldataadapter da=new sqldataadapter("select lastname, firstname, address,city from employees",this.sqlconnection1);
dataset ds=new dataset();
da.fill(ds,"employees");
this.datagrid1.datasource=ds;
this.datagrid1.datamember="employees";
//设置datagrid的各列
datagridtextboxcolumn c1=new datagridtextboxcolumn();
datagridtextboxcolumn c2=new datagridtextboxcolumn();
datagridtextboxcolumn c3=new datagridtextboxcolumn();
datagridtextboxcolumn c4=new datagridtextboxcolumn();
c1.mappingname="lastname";
c2.mappingname="firstname";
c3.mappingname="address";
c4.mappingname="city";
c1.headertext="lastname";
c2.headertext="firstname";
c3.headertext="address";
c4.headertext="city";
c1.widthchanged+=new eventhandler(this.abc);//列的宽变动时调整表头宽度
c2.widthchanged+=new eventhandler(this.abc);
c3.widthchanged+=new eventhandler(this.abc);
c4.widthchanged+=new eventhandler(this.abc);
datagridtablestyle dts=new datagridtablestyle();
dts.gridcolumnstyles.add(c1);
dts.gridcolumnstyles.add(c2);
dts.gridcolumnstyles.add(c3);
dts.gridcolumnstyles.add(c4);
dts.mappingname="employees"; this.datagrid1.tablestyles.add(dts);
//建立自画的表头类并将它们加入集合al
al=new arraylist();
topheadercolumn tc1=new topheadercolumn();
tc1.caption="name";
tc1.image=this.imagelist1.images[0];
tc1.columncollection.add(0);//记录它管辖的列的index
tc1.columncollection.add(1);
tc1.width=c1.width+c2.width;
topheadercolumn tc2=new topheadercolumn();
tc2.caption="address";
tc2.columncollection.add(2);
tc2.columncollection.add(3);
tc2.width=c3.width+c4.width;
al.add(tc1);
al.add(tc2);
this.datagrid1.paint += new system.windows.forms.painteventhandler(this.datagrid1_paint);
}
private void datagrid1_paint(object sender, system.windows.forms. painteventargs e)
{
int x=0;
//计算出第一个表头的左边距
int left=this.datagrid1.tablestyles[0].rowheaderwidth-this.datagrid1.hscrollbar.value;
//遍历表头集合al,画出表头
foreach (object o in this.al)
{
//计算出表头文字(文字居中)的左边距
x=left+(((topheadercolumn)o).width-convert.toint32(e.graphics. measurestring (((topheadercolumn)o).caption, this.datagrid1.captionfont). width))/2;
//完成表头绘制
if (((topheadercolumn)o).image!=null)
e.graphics.drawimage(((topheadercolumn)o).image,x-imagelist1.images[0].size.width,0);
e.graphics.drawstring(((topheadercolumn)o).caption,this.datagrid1. captionfont,new solidbrush(this.datagrid1.captionforecolor),x,0);
if (x>0)
e.graphics.drawline(new pen(color.black,2),left-1,0,left-1,this.datagrid1.height);
//计算出下一个表头的左边距
left+=((topheadercolumn)o).width;
}
if (x<this.datagrid1.width)
e.graphics.drawline(new pen(color.black,2),left-1,0,left-1,this.datagrid1.height);
}
private void abc(object sender,eventargs e)
{
//设置表头的宽度
foreach (object o in this.al)
{
((topheadercolumn)o).width=0;
foreach (int i in ((topheadercolumn)o).columncollection)
{ ((topheadercolumn)o).width+=this.datagrid1.tablestyles[0].gridcolumnstyles.width;
}
}
}
private void datagrid1_scroll(object sender, system.eventargs e)
{
this.datagrid1.refresh();
}
上面的代码实现了两层表头,至于三层表头也同理。
关于如何实现datagrid多层表头,许多网友都提到,目前好像没有一种特别好的方便的方法。如果那位网友发现了更好的方法,请给我留一条短训告知,谢谢。