扩展GridView控件(4) - 联动复选框(复选框的全选和取消全选)
GridView既强大又好用。为了让它更强大、更好用,我们来写一个继承自GridView的控件。
[索引页]
[源码下载]
作者:webabcd
介绍
扩展GridView控件:
联动复选框(复选框的全选和取消全选)。选中指定的父复选框,则设置指定的所有子复选框为选中状态;取消选中指定的父复选框,则设置指定的所有子复选框为取消选中状态。如果指定的所有子复选框为均选中状态,则设置指定的父复选框为选中状态;如果指定的所有子复选框至少有一个为取消选中状态,则设置指定的父复选框为取消选中状态
使用方法(设置CascadeCheckboxes集合属性):
ParentCheckboxID - 模板列中 父复选框ID
ChildCheckboxID - 模板列中 子复选框ID
YYControls.Helper.SmartGridView中的静态方法
List<DataKey> GetCheckedDataKey(GridView gv, int columnIndex)
List<DataKey> GetCheckedDataKey(GridView gv, string checkboxId)
关键代码
js
c#
介绍
平时使用GridView的时候经常要给每行加一个复选框,然后还需要放置一个单独的全选复选框,通过单击它来让这些复选框全选或取消全选,每次实现这样的功能都要写一段javascript,麻烦,所以扩展它。
控件开发
1、新建一个继承自GridView的类。
2、新建一个JavaScriptConstant类,把我们要用到的javascript存在一个常量里
3、新建一个CheckboxAll类,有两个属性
4、新建一个继承自CollectionBase的类CheckboxAlls
5、在继承自GridView的类中加一个复杂对象属性,该复杂对象就是第4步创建的那个CheckboxAlls
6、声明一些内部属性
7、声明几个私有变量
8、重写OnRowDataBound以给我们声明的那些私有变量赋值。
9、重写GridView的OnPreRender方法,以实现每行复选框的全选与取消全选的功能。
控件使用
添加这个控件到工具箱里,然后拖拽到webform上,在模板列的头模板处添加一个复选框,在模板列的项模板处添加一个复选框,设置控件的CheckboxAlls属性即可。CheckboxAllID是模板列全选复选框ID;CheckboxItemID是模板列项复选框ID。
ObjData.cs
Default.aspx
OK
[源码下载]
[索引页]
[源码下载]
扩展GridView控件(4) - 联动复选框(复选框的全选和取消全选)
作者:webabcd
/*正式版的实现 开始*/
介绍
扩展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[i]))
{
ccIndex = i;
break;
}
}
if (ccIndex != -1)
{
if (obj.id.yy_sgv_endsWith(yy_sgv_ccAll_post[i]))
{
yy_sgv_ccCheckAll(ccIndex, obj.checked);
}
else if (obj.id.yy_sgv_endsWith(yy_sgv_ccItem_post[i]))
{
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[i].type == 'checkbox'
&& elements[i].id.yy_sgv_startsWith(yy_sgv_ccGridView_pre[ccIndex])
&& elements[i].id.yy_sgv_endsWith(yy_sgv_ccItem_post[ccIndex]))
{
elements[i].checked = isCheckAll;
if (yy_sgv_crClassName != '')
{
yy_sgv_changeCheckedRowCssClass(elements[i], 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[i].type == 'checkbox'
&& elements[i].id.yy_sgv_startsWith(yy_sgv_ccGridView_pre[ccIndex])
&& elements[i].id.yy_sgv_endsWith(yy_sgv_ccItem_post[ccIndex]))
{
if (elements[i].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[i].type == 'checkbox'
&& elements[i].id.yy_sgv_startsWith(pre)
&& elements[i].id.yy_sgv_endsWith(post))
{
elements[i].checked = isCheckAll;
break;
}
}
}
function yy_sgv_ccListener()
{
/// <summary>监听所有联动复选框的单击事件</summary>
var elements = document.getElementsByTagName("INPUT");
for (i=0; i< elements.length; i++)
{
if (elements[i].type == 'checkbox')
{
for (j=0; j<yy_sgv_ccGridView_pre.length; j++)
{
if (elements[i].id.yy_sgv_startsWith(yy_sgv_ccGridView_pre[j])
&& (elements[i].id.yy_sgv_endsWith(yy_sgv_ccAll_post[j]) || elements[i].id.yy_sgv_endsWith(yy_sgv_ccItem_post[j])))
{
yy_sgv_addEvent(elements[i], 'click', yy_sgv_ccCheck);
break;
}
}
}
}
}
if (document.all)
{
window.attachEvent('onload', yy_sgv_ccListener)
}
else
{
window.addEventListener('load', yy_sgv_ccListener, false);
}
/*联动复选框 结束*/
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[i]))
{
ccIndex = i;
break;
}
}
if (ccIndex != -1)
{
if (obj.id.yy_sgv_endsWith(yy_sgv_ccAll_post[i]))
{
yy_sgv_ccCheckAll(ccIndex, obj.checked);
}
else if (obj.id.yy_sgv_endsWith(yy_sgv_ccItem_post[i]))
{
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[i].type == 'checkbox'
&& elements[i].id.yy_sgv_startsWith(yy_sgv_ccGridView_pre[ccIndex])
&& elements[i].id.yy_sgv_endsWith(yy_sgv_ccItem_post[ccIndex]))
{
elements[i].checked = isCheckAll;
if (yy_sgv_crClassName != '')
{
yy_sgv_changeCheckedRowCssClass(elements[i], 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[i].type == 'checkbox'
&& elements[i].id.yy_sgv_startsWith(yy_sgv_ccGridView_pre[ccIndex])
&& elements[i].id.yy_sgv_endsWith(yy_sgv_ccItem_post[ccIndex]))
{
if (elements[i].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[i].type == 'checkbox'
&& elements[i].id.yy_sgv_startsWith(pre)
&& elements[i].id.yy_sgv_endsWith(post))
{
elements[i].checked = isCheckAll;
break;
}
}
}
function yy_sgv_ccListener()
{
/// <summary>监听所有联动复选框的单击事件</summary>
var elements = document.getElementsByTagName("INPUT");
for (i=0; i< elements.length; i++)
{
if (elements[i].type == 'checkbox')
{
for (j=0; j<yy_sgv_ccGridView_pre.length; j++)
{
if (elements[i].id.yy_sgv_startsWith(yy_sgv_ccGridView_pre[j])
&& (elements[i].id.yy_sgv_endsWith(yy_sgv_ccAll_post[j]) || elements[i].id.yy_sgv_endsWith(yy_sgv_ccItem_post[j])))
{
yy_sgv_addEvent(elements[i], '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
);
}
}
}
}
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
{
}
/// 继承自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[i] == objAll.id)
{
// 该全选复选框同组下的项复选框数组
aryItem = aryItems[i].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[i].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[i]).checked = true;
}
// 否则
else
{
GetObject(aryAlls[i]).checked = false;
}
}
}
function GetObject(param)
{
return document.getElementById(param);
}
//]]>
</script>";
}
}
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[i] == objAll.id)
{
// 该全选复选框同组下的项复选框数组
aryItem = aryItems[i].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[i].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[i]).checked = true;
}
// 否则
else
{
GetObject(aryAlls[i]).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";
}
}
}
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);
}
}
}
}
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;
}
}
/// <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 '|'; }
}
/// 隐藏字段的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>();
/// 用于存每组的全选复选框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[i].Controls.Count; j++)
{
if (e.Row.Cells[i].Controls[j] is CheckBox)
{
CheckBox chk = (CheckBox)e.Row.Cells[i].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[i].Controls.Count; j++)
{
if (e.Row.Cells[i].Controls[j] is CheckBox)
{
CheckBox chk = (CheckBox)e.Row.Cells[i].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);
}
/// 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[i].Controls.Count; j++)
{
if (e.Row.Cells[i].Controls[j] is CheckBox)
{
CheckBox chk = (CheckBox)e.Row.Cells[i].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[i].Controls.Count; j++)
{
if (e.Row.Cells[i].Controls[j] is CheckBox)
{
CheckBox chk = (CheckBox)e.Row.Cells[i].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());
}
}
}
/// 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;
}
}
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>
<!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>
/*测试版的实现 结束*/
OK
[源码下载]