GridView是asp.net 2.0中,最常用、最好用的伺服器控件之一;但是,為了讓它更适應于我們具體的項目,我們很多時候,需要對它進行一些特殊操作。
如,實作如下效果

當然,我承認,實作如上效果并不複雜,
1、增加一個模版列放置複選框;
2、合并底部(footer)并放置三個LinkButton,即全選、反選、取消;并寫相應事件,使其可以操作各行中的複選框;
3、然後在OnRowDataBound事件中,給各個行加上JavaScript事件,使各個資料行可以響應滑鼠懸停,以及單擊事件;
4、當通過其它的操作(如點選删除按鈕)來操作資料行時,用foreach周遊各資料行即可;
問題是,我們的項目中,會非常頻繁的用到這個效果,作為一個懶人,每次要拷貝代碼,實在是太麻煩了。寫一個增強的GridView控件,才是明智之舉;
如上效果所示,這個增強GridView應該具備以下功能:
1、拖上來就能用,自帶一個選擇列;這個選擇列要能夠綁定資料(可選);也就是說,增強控件隻能比以前更友善,不能更複雜。
2、footer自動合并,并帶三個LinkButton;對複選框操作采用JavaScript方法,在用戶端執行,這樣無須重新整理頁面,操作更流暢;
3、能夠自動取出選中的行,不必再foreach周遊;
4、帶一些參數,可以選擇是否顯示“選擇列”,以及取選中行的主鍵值;
為了實作以上效果,要寫C#,也要寫JavaScript與Css;
例如,動态增加模版列,當然得寫C#代碼操作;利用控件的OnInit事件;
而資料行的滑鼠懸停與單擊,當然得寫JavaScript,用它來操作加載Css樣式;這裡我用了Jquery架構。
我在這裡把主要的C#代碼拿出來供學習吧。關鍵的地方我做了描述,當然,裡面有一些代碼寫得有備援,也是自己懶,不想在用戶端做太多判斷,直接辨別了資料行,如e.Row.Attributes.Add("RowType","DataRow");,之類的,都是為友善js在用戶端判斷。
代碼如下:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
namespace Company.CustomControl
{
[DefaultProperty("Text")]
[ToolboxData("<{0}:GridView runat=server></{0}:GridView>")]
public class GridView : System.Web.UI.WebControls.GridView
{
#region 屬性
[Bindable(true)]
[Category("Appearance")]
[DefaultValue("用于選擇的複選框所在資料列的,資料列名稱,即綁定值")]
[Localizable(true)]
public string SelectBoxKeyName
{
get
{
String s = (String)ViewState["SelectBoxKeyName"];
return ((s == null) ? "SelectBox" : s);
}
set
ViewState["SelectBoxKeyName"] = value;
}
[DefaultValue("是否顯示用于選擇的複選框的資料列")]
public bool ShowSelectBox
String s = (String)ViewState["ShowSelectBox"];
return Convert.ToBoolean(((s == null) ? "True" : s));
ViewState["ShowSelectBox"] = value.ToString();
/// <summary>
/// 擷取選中資料行的主鍵值
/// </summary>
[DefaultValue(" 擷取選中資料行的主鍵值")]
public string GetKeyValues
if (this.DataKeyNames.Length < 1)
{
return "";
}
string tmp = "";
foreach (GridViewRow vr in this.Rows)
if (vr.RowType == DataControlRowType.DataRow)
{
CheckBox cb = (CheckBox)vr.FindControl(this.SelectBoxKeyName);
if (cb.Checked)
{
tmp += this.DataKeys[vr.RowIndex].Value.ToString() + ",";
}
}
if (tmp.IndexOf(",") > -1)
tmp = tmp.Substring(0, tmp.LastIndexOf(","));
return tmp;
#endregion
protected override void OnDataBound(EventArgs e)
if (this.CssClass == String.Empty)
this.CssClass = "GridView";
base.OnDataBound(e);
protected override void OnInit(EventArgs e)
//綁定選擇框的列
if (this.ShowSelectBox)
TemplateField dcf = new TemplateField();
dcf.HeaderText = "選擇";
CheckTemplate mt = new CheckTemplate(this.SelectBoxKeyName);
dcf.ItemTemplate = mt;
this.Columns.Insert(0, dcf);
base.OnInit(e);
protected override void OnRowDataBound(GridViewRowEventArgs e)
//當為資料行時
if (e.Row.RowType == DataControlRowType.DataRow)
e.Row.Attributes.Add("RowType","DataRow");
//取主鍵的值
if (this.DataKeyNames != null && this.DataKeyNames.Length>0)
string val = this.DataKeys[e.Row.RowIndex].Value.ToString();
e.Row.Attributes.Add("DataKey", val);
e.Row.Cells[0].Attributes.Add("ItemType","SelectBox");
//底部欄的跨列
if (e.Row.RowType == DataControlRowType.Footer)
e.Row.Attributes.Add("RowType", "Footer");
int col = e.Row.Cells.Count;
e.Row.Cells[0].ColumnSpan = col;
while (--col > 0)
e.Row.Cells[col].Visible = false;
e.Row.Cells[0].Attributes.Add("ItemType", "SelectHandler");
e.Row.Cells[0].Text = "全選、反選、取消";
base.OnRowDataBound(e);
}
}
/// <summary>
/// 用于載入複選框的類,該類很重要,是用于自定義GridView模版列的必然方法;
/// </summary>
public class CheckTemplate : ITemplate
private string colname;
public CheckTemplate(string colname)
this.colname = colname;
public void InstantiateIn(Control container)
CheckBox cb = new CheckBox();
cb.ID = colname;
cb.CssClass = colname;
cb.Attributes.Add("ControlType", "SelectBox");
cb.DataBinding += new EventHandler(this.OnDataBinding);
container.Controls.Add(cb);
public void OnDataBinding(object sender, EventArgs e)
{
try
//用于資料綁定
CheckBox cb = (CheckBox)sender;
GridViewRow container = (GridViewRow)cb.NamingContainer;
//如果存在該資料列,則綁定;
cb.Checked = Convert.ToBoolean(((DataRowView)container.DataItem)[colname].ToString());
catch
//我不是有意要寫try,隻是當SelectBoxKeyName屬性為空時,即使用者并不想給選擇列綁定資料時,這裡不至于出錯;
//如果SelectBoxKeyName屬性不為空,其資料會自動綁定到選擇列上。
}
上面的控件,增加了三個屬性;
SelectBoxKeyName:這個是對選擇列進行資料綁定時的鍵值,如DataTable的列名;這個可以不填的。
ShowSelectBox:是否顯示的選擇列,預設為顯示;
GetKeyValues:擷取選中資料行的主鍵值;如果沒有主鍵,或沒有選中行,則傳回空字元,否則傳回主鍵清單字元串,用逗号分隔;如10,20,55,56;
使用很簡單,asp.net頁面中代碼如下
<%@ Register Assembly="Company.CustomControl" Namespace="Company.CustomControl" TagPrefix="cc1" %>
<cc1:GridView ID="GridView1" runat="server" ShowFooter="True">
</cc1:GridView>
綁定資料後,就顯示出如頂部圖中的效果。
我抽空把它整理出來,單獨放到一個項目中,做個完整示例,發上來吧。以上代碼,供參考學習;
完整示例做好了(vs2005 sp1):
GridViewDemo.rar