
mikecat
迈克老猫
-
个人空间
- 组别:管理员
- 性别:
- 来自:中国-石家庄
- 积分:2328
- 帖子:1996
- 注册:
2007-12-31
|
扩展GridView控件(4) - 联动复选框(复选框的全选和取消全选)
/*正式版的实现 开始*/ 介绍 扩展GridView控件: 联动复选框(复选框的全选和取消全选)。选中指定的父复选框,则设置指定的所有子复选框为选中状态;取消选中指定的父复选框,则设置指定的所有子复选框为取消选中状态。如果指定的所有子复选框为均选中状态,则设置指定的父复选框为选中状态;如果指定的所有子复选框至少有一个为取消选中状态,则设置指定的父复选框为取消选中状态 使用方法(设置CascadeCheckboxes集合属性): ParentCheckboxID - 模板列中 父复选框ID ChildCheckboxID - 模板列中 子复选框ID YYControls.Helper.SmartGridView中的静态方法 List<DataKey> GetCheckedDataKey(GridView gv, int columnIndex) List<DataKey> GetCheckedDataKey(GridView gv, string checkboxId) 关键代码 js /**//*联动复选框 开始*/ var yy_sgv_ccGridView_pre = new Array(); // cs中动态向其灌数据(GridView内控件ID的前缀数组) var yy_sgv_ccAll_post = new Array(); // cs中动态向其灌数据(全选复选框ID的后缀数组) var yy_sgv_ccItem_post = new Array(); // cs中动态向其灌数据(项复选框ID的后缀数组) function yy_sgv_ccCheck(e) { /// <summary>单击复选框时</summary> var evt = e || window.event; // FF || IE var obj = evt.target || evt.srcElement // FF || IE var ccIndex = -1; for (var i=0; i<yy_sgv_ccGridView_pre.length; i++) { if (obj.id.yy_sgv_startsWith(yy_sgv_ccGridView_pre )) { ccIndex = i; break; } } if (ccIndex != -1) { if (obj.id.yy_sgv_endsWith(yy_sgv_ccAll_post)) { yy_sgv_ccCheckAll(ccIndex, obj.checked); } else if (obj.id.yy_sgv_endsWith(yy_sgv_ccItem_post)) { yy_sgv_ccCheckItem(ccIndex); } } }
function yy_sgv_ccCheckAll(ccIndex, isCheckAll) { /// <summary>设置全选复选框的状态</summary>
var elements = document.getElementsByTagName("INPUT"); for (i=0; i< elements.length; i++) { if (elements.type == 'checkbox' && elements.id.yy_sgv_startsWith(yy_sgv_ccGridView_pre[ccIndex]) && elements.id.yy_sgv_endsWith(yy_sgv_ccItem_post[ccIndex])) { elements.checked = isCheckAll; if (yy_sgv_crClassName != '') { yy_sgv_changeCheckedRowCssClass(elements, yy_sgv_crClassName, false); } } } }
function yy_sgv_ccCheckItem(ccIndex) { /// <summary>单击项复选框时</summary>
var elements = document.getElementsByTagName("INPUT"); var checkedNum = 0; var uncheckedNum = 0; for (i=0; i< elements.length; i++) { if (elements.type == 'checkbox' && elements.id.yy_sgv_startsWith(yy_sgv_ccGridView_pre[ccIndex]) && elements.id.yy_sgv_endsWith(yy_sgv_ccItem_post[ccIndex])) { if (elements.checked) { checkedNum++; } else { uncheckedNum++; } } } if (uncheckedNum == 0) { yy_sgv_ccCheckCheckbox(yy_sgv_ccGridView_pre[ccIndex], yy_sgv_ccAll_post[ccIndex], true) } else { yy_sgv_ccCheckCheckbox(yy_sgv_ccGridView_pre[ccIndex], yy_sgv_ccAll_post[ccIndex], false) } }
function yy_sgv_ccCheckCheckbox(pre, post, isCheckAll) { /// <summary>设置项复选框的状态</summary>
var elements = document.getElementsByTagName("INPUT"); for (i=0; i< elements.length; i++) { if (elements.type == 'checkbox' && elements.id.yy_sgv_startsWith(pre) && elements.id.yy_sgv_endsWith(post)) { elements.checked = isCheckAll; break; } } }
function yy_sgv_ccListener() { /// <summary>监听所有联动复选框的单击事件</summary>
var elements = document.getElementsByTagName("INPUT"); for (i=0; i< elements.length; i++) { if (elements.type == 'checkbox') { for (j=0; j<yy_sgv_ccGridView_pre.length; j++) { if (elements.id.yy_sgv_startsWith(yy_sgv_ccGridView_pre[j]) && (elements.id.yy_sgv_endsWith(yy_sgv_ccAll_post[j]) || elements.id.yy_sgv_endsWith(yy_sgv_ccItem_post[j]))) { yy_sgv_addEvent(elements, 'click', yy_sgv_ccCheck); break; } } } } } if (document.all) { window.attachEvent('onload', yy_sgv_ccListener) } else { window.addEventListener('load', yy_sgv_ccListener, false); } /**//*联动复选框 结束*/
c# using System; using System.Collections.Generic; using System.Text;
using System.Web.UI.WebControls; using System.Web.UI;
namespace YYControls.SmartGridViewFunction { /**//// <summary> /// 扩展功能:联动复选框(复选框的全选和取消全选) /// </summary> public class CascadeCheckboxFunction : ExtendFunction { /**//// <summary> /// 构造函数 /// </summary> public CascadeCheckboxFunction() : base() {
}
/**//// <summary> /// 构造函数 /// </summary> /// <param name="sgv">SmartGridView对象</param> public CascadeCheckboxFunction(SmartGridView sgv) : base(sgv) {
}
/**//// <summary> /// 扩展功能的实现 /// </summary> protected override void Execute() { this._sgv.PreRender += new EventHandler(_sgv_PreRender); }
/**//// <summary> /// SmartGridView的PreRender事件 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> void _sgv_PreRender(object sender, EventArgs e) { // 构造向数组中添加成员的脚本 string scriptString = ""; foreach (CascadeCheckbox cc in this._sgv.CascadeCheckboxes) { scriptString += String.Format("yy_sgv_ccGridView_pre.push('{0}');", Helper.Common.GetChildControlPrefix(this._sgv)); scriptString += String.Format("yy_sgv_ccAll_post.push('{0}');", cc.ParentCheckboxID); scriptString += String.Format("yy_sgv_ccItem_post.push('{0}');", cc.ChildCheckboxID); }
// 注册向数组中添加成员的脚本 if (!this._sgv.Page.ClientScript.IsClientScriptBlockRegistered(String.Format("yy_sgv_cascadeCheckbox_{0}", this._sgv.ID))) { this._sgv.Page.ClientScript.RegisterClientScriptBlock ( this._sgv.GetType(), String.Format("yy_sgv_cascadeCheckbox_{0}", this._sgv.ID), scriptString, true ); } } } }
/*正式版的实现 结束*/
/*测试版的实现 开始*/
介绍 平时使用GridView的时候经常要给每行加一个复选框,然后还需要放置一个单独的全选复选框,通过单击它来让这些复选框全选或取消全选,每次实现这样的功能都要写一段javascript,麻烦,所以扩展它。
控件开发 1、新建一个继承自GridView的类。 /**//// <summary> /// 继承自GridView /// </summary> [ToolboxData(@"<{0}:SmartGridView runat='server'></{0}:SmartGridView>")] public class SmartGridView : GridView { }
2、新建一个JavaScriptConstant类,把我们要用到的javascript存在一个常量里 using System; using System.Collections.Generic; using System.Text;
namespace YYControls.SmartGridView { /**//// <summary> /// javascript /// </summary> public class JavaScriptConstant { internal const string jsCheckAll = @"<script type=""text/javascript""> //<![CDATA[
// 隐藏字段的ID,用于存每组的全选复选框ID var hdnAllName = '[$AllName$]'; // 隐藏字段的ID,用于存每的项复选框ID var hdnItemName = '[$ItemName$]'; // 组分隔符,一个 全选复选框 和其对应的n个 项复选框 为一个组 var groupSeparator = '[$GroupSeparator$]'; // 项分隔符,项复选框 每个项之间的分隔符 var itemSeparator = '[$ItemSeparator$]';
var strAlls = GetObject(hdnAllName).value; var strItems = GetObject(hdnItemName).value;
// 全选复选框数组 var aryAlls = strAlls.split(groupSeparator); // 项复选框数组,每行有一个组的所有项复选框 var aryItems = strItems.split(groupSeparator);
// 全选复选框被单击,参数为 该全选复选框这个对象 function ClickCheckAll(objAll) { // 每个全选复选框 for (var i=0; i<aryAlls.length; i++) { // 该全选复选框是所单击的全选复选框 if (aryAlls == objAll.id) { // 该全选复选框同组下的项复选框数组 aryItem = aryItems.split(itemSeparator); for (var j=0; j<aryItem.length; j++) { // 单击的全选复选框是选中状态,并且项复选框不是disabled,则选中 if (objAll.checked && !GetObject(aryItem[j]).parentElement.disabled) { GetObject(aryItem[j]).checked = true; } // 否则 else { GetObject(aryItem[j]).checked = false; } } break; } } }
// 项复选框被单击 function ClickCheckItem() { // 每组项复选框 for (var i=0; i<aryItems.length; i++) { // 该组的所有项复选框数组 aryItem = aryItems.split(itemSeparator); // 标记,是否同组的项复选框都被选中 var bln = true; for (var j=0; j<aryItem.length; j++) { // 如果该项复选框没被选中,并且不是disabled,则bln设为false if (!GetObject(aryItem[j]).checked && !GetObject(aryItem[j]).parentElement.disabled) { bln = false; break; } } // bln为true,则设置同组的全选复选框为选中 if (bln) { GetObject(aryAlls).checked = true; } // 否则 else { GetObject(aryAlls).checked = false; } } }
function GetObject(param) { return document.getElementById(param); }
//]]> </script>"; } }
3、新建一个CheckboxAll类,有两个属性 using System; using System.Collections.Generic; using System.Text;
using System.ComponentModel; using System.Web.UI;
namespace YYControls.SmartGridView { /**//// <summary> /// CheckboxAll 的摘要说明。 /// </summary> [ToolboxItem(false)] public class CheckboxAll { private string _checkboxAllID; /**//// <summary> /// 模板列全选复选框ID /// </summary> public string CheckboxAllID { get { return _checkboxAllID; } set { _checkboxAllID = value; } }
private string _checkboxItemID; /**//// <summary> /// 模板列项复选框ID /// </summary> public string CheckboxItemID { get { return _checkboxItemID; } set { _checkboxItemID = value; } }
/**//// <summary> /// ToString() /// </summary> /// <returns></returns> public override string ToString() { return "CheckboxAll"; } } }
4、新建一个继承自CollectionBase的类CheckboxAlls using System.Collections; using System.ComponentModel; using System.Web.UI;
namespace YYControls.SmartGridView { /**//// <summary> /// CheckboxAlls 的摘要说明。 /// 注意要继承自CollectionBase /// </summary> [ ToolboxItem(false), ParseChildren(true) ] public class CheckboxAlls : CollectionBase { /**//// <summary> /// 构造函数 /// </summary> public CheckboxAlls() : base() { }
/**//// <summary> /// 实现IList接口 /// 获取或设置指定索引处的元素。 /// </summary> /// <param name="index">要获得或设置的元素从零开始的索引</param> /// <returns></returns> public CheckboxAll this[int index] { get { return (CheckboxAll)base.List[index]; } set { base.List[index] = (CheckboxAll)value; } }
/**//// <summary> /// 实现IList接口 /// 将某项添加到 System.Collections.IList 中。 /// </summary> /// <param name="item">要添加到 System.Collections.IList 的 System.Object。</param> public void Add(CheckboxAll item) { base.List.Add(item); }
/**//// <summary> /// 实现IList接口 /// 从 System.Collections.IList 中移除特定对象的第一个匹配项。 /// </summary> /// <param name="index">要从 System.Collections.IList 移除的 System.Object</param> public void Remove(int index) { if (index > -1 && index < base.Count) { base.List.RemoveAt(index); } } } }
5、在继承自GridView的类中加一个复杂对象属性,该复杂对象就是第4步创建的那个CheckboxAlls private CheckboxAlls _checkboxAlls; /**//// <summary> /// 复选框组集合 一个组由一个 全选复选框 和多个 项复选框组成 /// </summary> [ PersistenceMode(PersistenceMode.InnerProperty), DesignerSerializationVisibility(DesignerSerializationVisibility.Content), Description("复选框组集合 一个组由一个 全选复选框 和多个 项复选框组成"), Category("扩展") ] public virtual CheckboxAlls CheckboxAlls { get { if (_checkboxAlls == null) { _checkboxAlls = new CheckboxAlls(); } return _checkboxAlls; } }
6、声明一些内部属性 /**//// <summary> /// 隐藏字段的ID,用于存每组的全选复选框ID /// </summary> protected string HiddenCheckboxAllID { get { return "hdn_checkboxAll"; } } /**//// <summary> /// 隐藏字段的ID,用于存每组的项复选框ID /// </summary> protected string HiddenCheckboxItemID { get { return "hdn_checkboxItem"; } }
/**//// <summary> /// 组分隔符,一个 全选复选框 和其对应的n个 项复选框 为一个组 /// </summary> protected char GroupSeparator { get { return ','; } } /**//// <summary> /// 项分隔符,项复选框 每个项之间的分隔符 /// </summary> protected char ItemSeparator { get { return '|'; } }
7、声明几个私有变量 /**//// <summary> /// 用于存每组的全选复选框ID /// </summary> private string _checkAllIDString; /**//// <summary> /// 用于存每的项复选框ID /// </summary> private string _checkItemIDString; /**//// <summary> /// 每行有一个组的所有项复选框 /// </summary> private Dictionary<int, string> _checkItemIDDictionary = new Dictionary<int, string>();
8、重写OnRowDataBound以给我们声明的那些私有变量赋值。 /**//// <summary> /// OnRowDataBound /// </summary> /// <param name="e"></param> protected override void OnRowDataBound(GridViewRowEventArgs e) { if (e.Row.RowType == DataControlRowType.DataRow) { // GridViewRow的每个TableCell for (int i = 0; i < e.Row.Cells.Count; i++) { // TableCell里的每个Control for (int j = 0; j < e.Row.Cells.Controls.Count; j++) { if (e.Row.Cells.Controls[j] is CheckBox) { CheckBox chk = (CheckBox)e.Row.Cells.Controls[j];
// 判断该CheckBox是否属于全选CheckBox bool isCheckboxAll = false; foreach (CheckboxAll ca in CheckboxAlls) { if (chk.NamingContainer.ClientID + "_" + ca.CheckboxItemID == chk.ClientID) { isCheckboxAll = true; break; } }
// 给该CheckBox增加客户端代码 if (isCheckboxAll) { // 给Control增加一个客户端onclick chk.Attributes.Add("onclick", "yy_ClickCheckItem()"); // 给_checkItemIDDictionary赋值 if (_checkItemIDDictionary.Count == 0 || !_checkItemIDDictionary.ContainsKey(i)) { _checkItemIDDictionary.Add(i, chk.ClientID); } else { string s; _checkItemIDDictionary.TryGetValue(i, out s); _checkItemIDDictionary.Remove(i); _checkItemIDDictionary.Add(i, s + this.ItemSeparator + chk.ClientID); }
break; } } } } } else if (e.Row.RowType == DataControlRowType.Header) { // GridViewRow的每个TableCell for (int i = 0; i < e.Row.Cells.Count; i++) { // TableCell里的每个Control for (int j = 0; j < e.Row.Cells.Controls.Count; j++) { if (e.Row.Cells.Controls[j] is CheckBox) { CheckBox chk = (CheckBox)e.Row.Cells.Controls[j];
// 判断该CheckBox是否属于全选CheckBox bool isCheckboxAll = false; foreach (CheckboxAll ca in CheckboxAlls) { if (chk.NamingContainer.ClientID + "_" + ca.CheckboxAllID == chk.ClientID) { isCheckboxAll = true; break; } }
// 给该CheckBox增加客户端代码 if (isCheckboxAll) { // 给Control增加一个客户端onclick chk.Attributes.Add("onclick", "yy_ClickCheckAll(this)"); // 给_checkAllIDString赋值 if (String.IsNullOrEmpty(this._checkAllIDString)) { this._checkAllIDString += chk.ClientID; } else { this._checkAllIDString += this.GroupSeparator + chk.ClientID; } break; } } } } }
base.OnRowDataBound(e); }
9、重写GridView的OnPreRender方法,以实现每行复选框的全选与取消全选的功能。 /**//// <summary> /// OnPreRender /// </summary> /// <param name="e"></param> protected override void OnPreRender(EventArgs e) { base.OnPreRender(e);
// CheckboxAlls里有对象则注册一些完成实现全选功能的客户端脚本 if (CheckboxAlls.Count > 0) { // 注册实现 每行复选框的全选与取消全选 功能的JavaScript if (!Page.ClientScript.IsClientScriptBlockRegistered("JsCheckAll")) { Page.ClientScript.RegisterClientScriptBlock( this.GetType(), "JsCheckAll", JavaScriptConstant.jsCheckAll.Replace("[$AllName$]", this.HiddenCheckboxAllID).Replace("[$ItemName$]", this.HiddenCheckboxItemID).Replace("[$GroupSeparator$]", this.GroupSeparator.ToString()).Replace("[$ItemSeparator$]", this.ItemSeparator.ToString()) ); }
// 给_checkItemIDString赋值 _checkItemIDString = ""; foreach (KeyValuePair<int, string> kvp in _checkItemIDDictionary) { _checkItemIDString += this.GroupSeparator + kvp.Value; } if (_checkItemIDString.StartsWith(this.GroupSeparator.ToString())) { _checkItemIDString = _checkItemIDString.Remove(0, 1); }
// 注册实现 每行复选框的全选与取消全选 功能的两个隐藏字段 // 有的时候回发后没有重新绑定GridView,就会造成_checkAllIDString和_checkItemIDString为空 // 所以把这两个值存到ViewSate中 if (!String.IsNullOrEmpty(_checkAllIDString) && !String.IsNullOrEmpty(_checkItemIDString)) { ViewState[this.HiddenCheckboxAllID] = _checkAllIDString; ViewState[this.HiddenCheckboxItemID] = _checkItemIDString; } if (ViewState[this.HiddenCheckboxAllID] != null && ViewState[this.HiddenCheckboxItemID] != null) { Page.ClientScript.RegisterHiddenField(this.HiddenCheckboxAllID, ViewState[this.HiddenCheckboxAllID].ToString()); Page.ClientScript.RegisterHiddenField(this.HiddenCheckboxItemID, ViewState[this.HiddenCheckboxItemID].ToString()); } } }
控件使用 添加这个控件到工具箱里,然后拖拽到webform上,在模板列的头模板处添加一个复选框,在模板列的项模板处添加一个复选框,设置控件的 CheckboxAlls属性即可。CheckboxAllID是模板列全选复选框ID;CheckboxItemID是模板列项复选框ID。 ObjData.cs 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.ComponentModel;
/**//// <summary> /// OjbData 的摘要说明 /// </summary> public class OjbData { public OjbData() { // // TODO: 在此处添加构造函数逻辑 // }
[DataObjectMethod(DataObjectMethodType.Select, true)] public DataTable Select() { DataTable dt = new DataTable(); dt.Columns.Add("no", typeof(string)); dt.Columns.Add("name", typeof(string));
for (int i = 0; i < 30; i++) { DataRow dr = dt.NewRow(); dr[0] = "no" + i.ToString().PadLeft(2, '0'); dr[1] = "name" + i.ToString().PadLeft(2, '0');
dt.Rows.Add(dr); }
return dt; } }
Default.aspx <%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <title>SmartGridView测试</title> </head> <body> <form id="form1" runat="server"> <div> <yyc:SmartGridView ID="SmartGridView1" runat="server" AutoGenerateColumns="False" DataSourceID="ObjectDataSource1" Width="100%"> <Columns> <asp:TemplateField> <headertemplate> <asp:checkbox id="checkall" runat="server" /> </headertemplate> <itemtemplate> <asp:checkbox id="checkitem" runat="server" /> </itemtemplate> </asp:TemplateField> <asp:TemplateField> <itemtemplate> abc </itemtemplate> </asp:TemplateField> <asp:TemplateField> <headertemplate> <asp:checkbox id="checkall2" runat="server" /> </headertemplate> <itemtemplate> <asp:checkbox id="checkitem2" runat="server" /> </itemtemplate> </asp:TemplateField> </Columns> <CheckboxAlls> <yyc:CheckboxAll CheckboxAllID="checkall" CheckboxItemID="checkitem" /> <yyc:CheckboxAll CheckboxAllID="checkall2" CheckboxItemID="checkitem2" /> </CheckboxAlls> <SortTip SortAscImage="~/Images/asc.gif" SortDescImage="~/Images/desc.gif" /> </yyc:SmartGridView> <asp:ObjectDataSource ID="ObjectDataSource1" runat="server" SelectMethod="Select" TypeName="OjbData"></asp:ObjectDataSource> </div> </form> </body> </html>
/*测试版的实现 结束*/
原文出处:http://www.cnblogs.com/webabcd/
|