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[i].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="收入方式物業項目收入方式編號收入方式名稱";
}