.net中datagrid多层表头(winfrom和webform)
1. winform:
首先需要编写一个类来表示自画的表头,这个类将记录表头的显示文本、图标和属于它管辖的列的信息。
using system;
using system.collections;
using system.drawing;
namespace example
{
///
/// 表头类
///
public class topheadercolumn
{
public topheadercolumn()
{
columncollection=new arraylist();
}
//用于记录表头管辖的各列的信息
private arraylist columncollection;
public arraylist columncollection
{
get
{
return columncollection;
}
set
{
columncollection=value;
}
}
//表头的显示文本
private string caption;
public string caption
{
get
{
return caption;
}
set
{
caption=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做一点修改。编写基于datagrid控件的新控件mydata.
public class mydatagrid:datagrid
{
//取得水平滚动条的位置
public scrollbar hscrollbar
{
get
{
return horizscrollbar;
}
}
}
好了,可以工作了。在工具箱加入加入mydatagrid,新建一个window应用程序,一个mydatagrid和imagelist,连接sql数据库northwind。当然,还得加入上面的topheadercolumn类。
private void bind()
...{
sqlconnection con=new sqlconnection("server=.;uid=sa;pwd=;database=northwind;");
con.open();
sqldataadapter sda=new sqldataadapter();
sda.selectcommand=new sqlcommand("select lastname,firstname,address,city from employees",con);
dataset ds=new dataset();
sda.fill(ds,"employees");
dgdata.datasource=ds;
dgdata.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";
dgdata.tablestyles.add(dts);
//建立自画的表头类并将它们加入集合al
al=new arraylist();
topheadercolumn tc1=new topheadercolumn();
tc1.caption="name";
tc1.image=imagelist1.images[0];
//记录它管辖列的index
tc1.columncollection.add(0);
tc1.columncollection.add(1);
tc1.width=c1.width+c2.width;
topheadercolumn tc2=new topheadercolumn();
tc2.caption="address";
tc2.image=imagelist1.images[1];
tc2.columncollection.add(2);
tc2.columncollection.add(3);
tc2.width=c3.width+c4.width;
al.add(tc1);
al.add(tc2);
dgdata.paint+=new painteventhandler(dgdata_paint);
}
private void dgdata_paint(object sender,system.windows.forms.painteventargs e)
...{
int x=0;
//计算出第一个表头的左边距
int left=dgdata.tablestyles[0].rowheaderwidth-dgdata.hscrollbar.value;
//遍利表头集合al,画出表头
foreach(object o in al)
...{
//计算出表头文字的左边距
x=left+(((topheadercolumn)o).width-convert.toint32(e.graphics.measurestring(((topheadercolumn)o).caption,dgdata.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,dgdata.captionfont,new solidbrush(dgdata.captionforecolor),x,0);
if(x>0)
e.graphics.drawline(new pen(color.black,2),left-1,0,left-1,dgdata.height);
//计算下一个表头的左边距
left+=((topheadercolumn)o).width;
}
if(x e.graphics.drawline(new pen(color.black,2),left-1,0,left-1,dgdata.height);
}
private void abc(object sender,eventargs e)
...{
//设置表头的宽度
foreach(object o in al)
...{
((topheadercolumn)o).width=0;
foreach(int i in ((topheadercolumn)o).columncollection)
...{
((topheadercolumn)o).width+=dgdata.tablestyles[0].gridcolumnstyles.width;
}
}
}
好了,完成,运行下试试。上面的代码实现了两层表头,至于三层表头也同理。其中:sda.fill(ds,"employees");如果写成sda.fill(ds);的话,.net会提示你无法创建employees的子列表。
2. webfrom:
webform下就更简单了。实际上asp.net下的datagrid只不过是一个htmltable,只不过在htmltable的基础上添加了很多属性、方法,纳入viewstate机制,来生成、控制它;有了这一点认识,事情就很好办了:适用有模版列。
datagrid的itemcreated事件中处理:
if(e.item.itemtype==listitemtype.header)
{
tablecellcollection tcl=e.item.cells;
tcl.clear();
tcl.add(new tableheadercell());
tcl[0].rowspan=2;
tcl[0].text="no.";
tcl.add(new tableheadercell());
tcl[1].rowspan=2;
tcl[1].text="
<input id='chkselall' type='checkbox' name='chkselall' onclick='javascript:checkall(form1,this.checked);'/>
";
tcl.add(new tableheadercell());
tcl[2].rowspan=2;
tcl[2].text="修改";
tcl.add(new tableheadercell());
tcl[3].columnspan=3;
tcl[3].text="收入方式物业项目收入方式编号收入方式名称";