擴展GridView控件--增加選擇列
效果演示地址:http://demo.yuefan.net/
GridView是asp.net 2.0中,最常用、最好用的服務器控件之一;但是,為了讓它更適應于我們具體的項目,我們很多時候,需要對它進行一些特殊操作。
如,實現如下效果(如果下圖看不到,可以到我的百度空間看:擴展GridView控件--增加選擇列)

當然,我承認,實現如上效果并不復雜,
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;
}
}
[Bindable(true)]
[Category("Appearance")]
[DefaultValue("是否顯示用于選擇的復選框的數據列")]
[Localizable(true)]
public bool ShowSelectBox
{
get
{
String s = (String)ViewState["ShowSelectBox"];
return Convert.ToBoolean(((s == null) ? "True" : s));
}
set
{
ViewState["ShowSelectBox"] = value.ToString();
}
}
/// <summary>
/// 獲取選中數據行的主鍵值
/// </summary>
[Bindable(true)]
[DefaultValue(" 獲取選中數據行的主鍵值")]
[Localizable(true)]
[Category("Appearance")]
public string GetKeyValues
{
get
{
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
浙公網安備 33010602011771號