我們.Net俱樂部的一位朋友需要一個gridvIEw的多表頭實現,現給出兩種實現
方法一:
轉自:http://blog.csdn.Net/ankoe/archive/2007/10/29/1854361.ASPx
表頭定義說明:
表頭定義方法:相鄰父列頭之間用''#''分隔,上級行與下級行用空格('' '')分隔,相鄰未級子列頭用逗號分隔('','').
表頭定義示例:
A.兩層

煙葉等級#級別#保山市 保山,小計#楚雄州 姚安,小計#大理州 賓川,大理,小計#紅河州 建水,泸西,彌勒,石屏,小計#昆明市 富民,祿勸,小計#麗江市 華坪,寧蒗,小計#臨滄市 滄源,鳳慶,耿馬,臨翔,雙江,永德,雲縣,鎮康,小計#普洱市 景東,思茅,鎮沅,小計#曲靖市 富源,陸良,羅平,師宗,宣威,小計#文山州 文山,小計#玉溪市 玉溪,小計#總計
B.三層

等級#級別#上期結存 件數,重量,比例#本期調入 收購調入 件數,重量,比例#本期發出 車間投料 件數,重量,比例#本期發出 產品外銷百分比 件數,重量,比例#平均值
調用說明:使用時在GridVIEw的RowCreated事件中加入下面代碼調用

if (e.Row.RowType == DataControlRowType.Header)


...{

DynamicTHeaderHepler dHelper = new DynamicTHeaderHepler();

string header = "等級#級別#上期結存 件數,重量,比例#本期調入 收購調入 件數,重量,比例#本期發出 車間投料 件數,重量,"

+ "比例#本期發出 產品外銷百分比 件數,重量,比例#平均值";


dHelper.SplitTableHeader(e.Row, header);

}
表頭生成類:

//

//***********************************************************************

// Created: 2007-10-29 Author: ruijc

// File: DynamicTHeaderHepler.cs

// Description: 動態生成復合表頭幫助類

// 相鄰父列頭之間用''#''分隔,父列頭與子列頭用空格('' '')分隔,相鄰子列頭用逗號分隔('','').

//***********************************************************************

using System;

using System.Data;

using System.Configuration;

using System.Web;

using System.Web.Security;

using System.Web.UI;

using System.Web.UI.WebControls;

using System.Web.UI.WebControls.WebParts;

using System.Web.UI.HtmlControls;

using System.Collections.Generic;

using System.Collections;

public class DynamicTHeaderHepler


...{

public DynamicTHeaderHepler()


...{

//

// TODO: Add constructor logic here

//

}



/**//// <summary>

/// 重寫表頭

/// </summary>

/// <param name="targetHeader">目標表頭</param>

/// <param name="newHeaderNames">新表頭</param>

/// <remarks>

/// 等級#級別#上期結存 件數,重量,比例#本期調入 收購調入 件數,重量,比例#本期發出 車間投料 件數,重量,

/// 比例#本期發出 產品外銷百分比 件數,重量,比例#平均值

/// </remarks>


public void SplitTableHeader(GridVIEwRow targetHeader, string newHeaderNames)...{

; TableCellCollection tcl = targetHeader.Cells;//獲得表頭元素的實例

tcl.Clear();//清除元素

int row = GetRowCount(newHeaderNames);

int col = GetColCount(newHeaderNames);

string[,] nameList = ConvertList(newHeaderNames,row,col);

int RowSpan = 0;

int ColSpan = 0;

for (int k = 0; k < row; k++)


...{

string LastFName = "";

for (int i = 0; i < col; i++)


...{

if (LastFName == nameList[i, k] && k!=row-1)


...{

LastFName = nameList[i, k];

continue;

}

else

...{

LastFName = nameList[i, k];

}

int bFlag=IsVisible(nameList, k, i, LastFName);

switch (bFlag)


...{

case 0:

break;

case 1:

RowSpan = GetSpanRowCount(nameList,row, k, i);

ColSpan = GetSpanColCount(nameList,row,col, k, i);

tcl.Add(new TableHeaderCell());//添加表頭控件

tcl[tcl.Count - 1].RowSpan = RowSpan;

tcl[tcl.Count - 1].ColumnSpan = ColSpan;

tcl[tcl.Count - 1].HorizontalAlign = HorizontalAlign.Center;

tcl[tcl.Count - 1].Text = LastFName;

break;

case -1:


string[] EndColName = LastFName.Split(new char[] ...{ '','' });


foreach(string eName in EndColName)...{

tcl.Add(new TableHeaderCell());//添加表頭控件

tcl[tcl.Count - 1].HorizontalAlign = HorizontalAlign.Center;

tcl[tcl.Count - 1].Text = eName;

}

break;

}

}

if (k != row-1)


...{//不是起始行,加入新行標簽

tcl[tcl.Count - 1].Text = tcl[tcl.Count - 1].Text+"</th></tr><tr>";

}

}

}



/**//// <summary>

/// 如果上一行已經輸出和當前內容相同的列頭,則不顯示

/// </summary>

/// <param name="ColumnList">表頭集合</param>

/// <param name="rowIndex">行索引</param>

/// <param name="colIndex">列索引</param>

/// <returns>1:顯示,-1:含'',''分隔符,0:不顯示</returns>

private int IsVisible(string[,] ColumnList,int rowIndex, int colIndex,string CurrName)


...{


if (rowIndex!=0)...{


if (ColumnList[colIndex,rowIndex-1]==CurrName)...{

return 0;


}else...{

if (ColumnList[colIndex, rowIndex].Contains(","))


...{

return -1;


}else...{

return 1;

}

}

}

return 1;

}



/**//// <summary>

/// 取得和當前索引行及列對應的下級的內容所跨的行數

/// </summary>

/// <param name="ColumnList">表頭集合</param>

/// <param name="row">行數</param>

/// <param name="rowIndex">行索引</param>

/// <param name="colIndex">列索引</param>

/// <returns>行數</returns>

private int GetSpanRowCount(string[,] ColumnList, int row,int rowIndex, int colIndex)


...{

string LastName = "";

int RowSpan = 1;

for (int k = rowIndex; k < row; k++)


...{


if (ColumnList[colIndex,k]==LastName)...{

RowSpan++;


}else...{

LastName = ColumnList[colIndex, k];

}

}

return RowSpan;

}




...{

string LastName = "";

int RowSpan = 1;

for (int k = rowIndex; k < row; k++)


...{


if (ColumnList[colIndex,k]==LastName)...{

RowSpan++;


}else...{

LastName = ColumnList[colIndex, k];

}

}

return RowSpan;

}



...{


ColSpan += ColumnList[i, row - 1].Split(new char[] ...{ '','' }).Length;

}

else


...{

LastName = ColumnList[i, rowIndex];

break;

}

}

return ColSpan;

}



/**//// <summary>

/// 將已定義的表頭保存到數組

/// </summary>

/// <param name="newHeaders">新表頭</param>

/// <param name="row">行數</param>

/// <param name="col">列數</param>

/// <returns>表頭數組</returns>

private string[,] ConvertList(string newHeaders, int row, int col)


...{


string[] ColumnNames = newHeaders.Split(new char[] ...{ ''#'' });

string[,] news = new string[col, row];

string Name = "";

for (int i = 0; i < col; i++)


...{


string[] CurrColNames = ColumnNames[i].ToString().Split(new char[] ...{ '' '' });

for (int k = 0; k < row; k++)


...{

if (CurrColNames.Length - 1 >= k)


...{

if (CurrColNames[k].Contains(","))


...{

if (CurrColNames.Length != row)


...{

if (Name == "")


...{

news[i, k] = news[i, k - 1];


}else...{


news[i, k] = Name;

Name = "";

}

}

}

}

return news;

}



/**//// <summary>

/// 取得復合表頭的行數

/// </summary>

/// <param name="newHeaders">新表頭</param>

/// <returns>行數</returns>

private int GetRowCount(string newHeaders)


...{


string[] ColumnNames = newHeaders.Split(new char[] ...{ ''#'' });

int Count = 0;


foreach(string name in ColumnNames)...{


int TempCount = name.Split(new char[] ...{ '' '' }).Length;

if (TempCount > Count)

Count = TempCount;

}

return Count;

}



/**//// <summary>

/// 取得復合表頭的列數

/// </summary>

/// <param name="newHeaders">新表頭</param>

/// <returns>列數</returns>


private int GetColCount(string newHeaders)...{


return newHeaders.Split(new char[] ...{ ''#'' }).Length;

}

}
方法二:
出處不明

表格的多行復合表頭是在開發中經常遇到的問題,怎麼擴展GridVIEw控件以實現多行表頭呢
主體思路是這樣的,GridVIEw在ASP.Net中最終是轉化為Html的表格格式來顯示的,所以我們要在其中做點文章,
看下面這段代碼:
//在GridVIEw的RowCreated事件中重寫表頭
protected void GridView1_RowCreated(object sender, GridVIEwRowEventArgs e)
{
判斷創建的行是不是標題行
if (e.Row.RowType == DataControlRowType.Header)
{
TableCellCollection tcl = e.Row.Cells;
//清除自動生成的表頭
tcl.Clear();
//添加新的表頭
tcl.Add(new TableHeaderCell());
tcl[0].RowSpan = 2;
tcl[0].Text = "標題s";
Label l1 = new Label();
l1.Text = "uu";
Button bt = new Button();
bt.Text = "1";
//因為自定義表頭,所以原來系統中實現的排序功能就失效了
//下面語句可以自己在表頭中添加控件,自己實現排序功能
tcl[0].Controls.Add(l1);
tcl[0].Controls.Add(bt);
tcl.Add(new TableHeaderCell());
tcl[1].ColumnSpan = 2;
tcl[1].Text = "標題2";
tcl.Add(new TableHeaderCell());
tcl[2].RowSpan = 2;
tcl[2].Text = "標題3";
tcl.Add(new TableHeaderCell());
tcl[3].ColumnSpan = 3;
tcl[3].Text = "標題4";
tcl.Add(new TableHeaderCell());
tcl[4].RowSpan = 2;
//這段是重點 其實在生成的Html中tcl[4]轉化為<th>標題5</th>
//所以依照該原則注入Html標簽來實現,原理有些類似於SQL注入攻擊
tcl[4].Text = "標題5</th></tr><tr><th>標題2-1</th><th>標題2-2</th><th>標題4-1</th><th>標題4-2</th><標題4-3";
}
}
評論:
兩種方法都有一個缺點就是對動態生成的列支持不好,方法二可能更不穩定一點。