GridView既强大又好用。为了让它更强大、更好用,我们来写一个继承自GridView的控件。
[索引页]
[源码下载]
扩展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);
}

/**//*联动复选框 结束*/

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"">
//<
// 隐藏字段的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";
}
}
}

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[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());
}
}
}

控件使用
添加这个控件到工具箱里,然后拖拽到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>

/*测试版的实现 结束*/
OK
[源码下载]
Feedback
昨天发现这个好东西,晚上就试试看,发现,在单击了任何一行的按钮后,全选就失效了,不知道是我的配置问题,还是作者这个控件的一点儿瑕疵?
@赵志扬
发现问题了,谢谢兄弟提醒
因为在一个隐藏控件里会存储每行的复选框的ID,而获取这些ID是在RowDataBound事件中,如果回发后没有重新绑定GridView就不会执行这个事件
已经解决了这个BUG,把这些ID放到ViewState中了
再次感谢!
@6521
我又测了一遍,没问题啊
出错原因和改的办法就是
我在一个隐藏控件里会存储每行的复选框的ID,而获取这些ID是在RowDataBound事件中,如果回发后没有重新绑定GridView就不会执行这个事件
所以我就把这些ID放到ViewState中,问题就解决了
@谷中游
这样做
foreach (GridViewRow gvr in SmartGridView1.Rows)
{
if (gvr.RowType == DataControlRowType.DataRow)
{
CheckBox chk = gvr.Cells[0].FindControl("chk") as CheckBox;
if (chk.Checked)
{
// your code
}
}
}
能现实跨页选择吗?现在换页后,再回来, 上次选择的会不见了:(
@细节决定成败,习惯决定未来
现在是不行的
要实现的话可以把被选中的行的关键字列表存到ViewState里,每次加载页面的时候再读ViewState,从而设置每行的选中状态
老大,我们在实际的工作中常需要的1个数据列需要使用全选的复选框,你这个程序可以定义多个,虽然功能强大,但是阅读和使用起来均比较烦琐,能不能出一个简化版:
全选复选框就只有一个,而每行中也只有一列与之相对应
你的代码我修改了半天,就是搞不定
@刚接触自定义控件
控件的开发上确实是麻烦了一点,但是使用起来还应该算是简单并且直观的
如果只有一个数据列需要用这个功能的话,那么
<CheckboxAlls>
<yyc:CheckboxAll CheckboxAllID="checkall" heckboxItemID="checkitem" />
</CheckboxAlls>
我的想法是这样的,我只在属性控件的属性中直接选择控件的ID就可以了,不想在属性中通过box控后再选择我所需要的控件ID,我这样的做法是想使用起来更加简单一些。
另外,对于固定表头的做法,下面网页中提供了使用CSS的方法操作,但我不知道怎么样加入到控件中,要是可以把这些功能都加入到我们自定义的GridView,那就好了:)
http://blog.csdn.net/fe27/archive/2007/04/15/1565460.aspx
@刚接触自定义控件
肯定是可以的,定义个属性,然后重写GridView的某些方法的时候判断一下就好了
用CSS固定行、列,我已经做成了一个自定义控件,兄弟可以参考一下
http://www.cnblogs.com/webabcd/archive/2007/01/15/620501.html
@老夫子系
以我提供的那个测试程序为例
名为“yy_hdn_checkboxItem”的隐藏字段存储了所有的checkbox的id
document.getElementById("checkbox的id");
就ok了
大哥,用了你的这个扩展后,我怎么才能得到check所选择check列,ID的值呢。
我的想法是用将check列邦定ID,然后将我所选中的行一次删除。
怎么实现呀,大哥。。。快帮帮忙呀。
@bkhmjgtc
foreach (GridViewRow gvr in SmartGridView1.Rows)
{
if (gvr.RowType == DataControlRowType.DataRow)
{
CheckBox chk = gvr.Cells[0].FindControl("chk") as CheckBox;
if (chk.Checked)
{
// your code
}
}
}
正式版的时候会有一个helper类,用于获取GridView中通过复选框选中的行的DataKey集合,正式版肯定会在8月初之前放出来的
我试了一下,如果翻页的话,上一页所选的全部每了啊?
如果想在第一页选择一些项,在第二页页选择一些项,再回到第一页的时候,仍然保存以前所选中的项,如果点击删除,那么会删除所有选中的项。(第一页选中的和第二页选中的)。
如果想要上述效果,怎样实现啊?各位高手帮帮忙啊!~
@niuyy
要实现的话可以把被选中的行的关键字列表存到ViewState里,每次加载页面的时候再读ViewState,从而设置每行的选中状态
一个挺奇怪的问题:
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);
}
加到那个文件里就提示 elements 对象未引用
我把上面在文件里的代码注释掉,复制到测试页上,就没有问题。
@Matt Fang
没看太明白
“加到那个文件里 ”是什么意思?
那个文件就是ScriptLibraryDebug.js
@Matt Fang
不会啊
程序我测试过的,没问题
你是在运行demo的时候报错吗?
复选框的全选和取消全选 不是只要写一个函数就可以了吗?
ysdt54@sina.com
@啊特
开发的过程比较麻烦
换来的就是使用起来非常简单
webabcd:大哥你好
我运行这程序,你使用了联动复选框(复选框的全选和取消全选)这事件给谁用了?我没发现它们的作用,测试没测出来。。。嘿嘿,不才望指点疑点
@~宝贝不哭~
用这个监听checkbox的click事件
if (document.all)
{
window.attachEvent('onload', yy_sgv_ccListener)
}
else
{
window.addEventListener('load', yy_sgv_ccListener, false);
}
然后再在checkbox被单击后做判断
楼主的SmartGridView很好用,只是好象还有一个问题,在分页模式下,复选框无法跨页选取
@黄河
是的
你可以自己实现一下,把状态存到ViewState或Cookie里
写这个控件有太多的不尽如人意的地方,我打算在扩展ListView的时候把该改进的都改进了
<yyc:SmartGridView ID="SmartGridView1" DataKeys="id" DataSourceID="SqlDataSource1"
runat="server" ....
请问如何得到选 择行的id
谢谢
@abis
提供了一个帮助类
YYControls.Helper.SmartGridView中的静态方法
List GetCheckedDataKey(GridView gv, int columnIndex)
List GetCheckedDataKey(GridView gv, string checkboxId)
在IE7.0中提示yy_sgv_ccgridview_pre未定义
@cr
做什么操作导致出现这个问题的?
我测试时未发现此问题啊
大哥,用了你的这个扩展后,我怎么才能得到check所选择check列,ID的值呢。
我的想法是用将check列邦定ID,然后将我所选中的行一次删除。
怎么实现呀,大哥。。。快帮帮忙呀。
能给个示例哇,谢谢了
@土豆快跑
取出选中的项
List<DataKey> GetCheckedDataKey(GridView gv, int columnIndex)
List<DataKey> GetCheckedDataKey(GridView gv, string checkboxId)
List<DataKey> GetCheckedDataKey(GridView gv, int columnIndex)
List<DataKey> GetCheckedDataKey(GridView gv, string checkboxId)
但string checkboxId,比方说你那个示例里的
<asp:TemplateField ItemStyle-Width="50px">
<headertemplate>
<asp:CheckBox ID="all" runat="server" />
</headertemplate>
<itemtemplate>
<asp:CheckBox ID="item" runat="server" />
</itemtemplate>
</asp:TemplateField>
“item”是找不到的啊,报错啊,大哥
List<DataKey> GetCheckedDataKey(GridView gv, int columnIndex)
这种方法如何使用?掉不出来,请指教
有用过这个控件的朋友请指教,这个方法如何使用?
List<DataKey> GetCheckedDataKey(GridView gv, int columnIndex)
@seek.net
/// <summary>
/// 获取GridView中通过复选框选中的行的DataKey集合
/// </summary>
/// <param name="gv">GridView</param>
/// <param name="columnIndex">CheckBox在GridView中的列索引</param>
类全名:YYControls.Helper.SmartGridView
我能不能得到选中复选框所在行中的任意列的值。
怎么取值。谢谢。
请教:
我如何可在调用GridView的页面客户端获取所选checkbox的id或是GridView的datakey
我想在页面选择某些行后跳到另一页作处理,而本必须在处理后才可刷新,所以不能用你提供的服务器方法
@克隆
用js遍历checkbox,在服务端给checkbox加一个attribute用于保存id,之后可由js读到
@webabcd
多谢,我试试你的方法,原来我一直用一个与checkbox ID 相近的隐藏域,感觉这样获取比较麻烦
@克隆
嗯,反正也是能实现需求的
当然,要想条理清楚点的话最好是加一个attribute
发现问题:
当SmartGridView用后台代码
SmartGridView1.DataSource = table;
SmartGridView1.DataBind();
绑定数据时
List<DataKey> GetCheckedDataKey(GridView gv, int columnIndex)
取不出DataKey,据观察是因为没有检测到(CheckBox)c).Checked
像这种<yyc:SmartGridView ID="sgv1" runat="server" DataSourceID="ObjectDataSource1"前台方式绑定时,没有问题。
怎么办@_@
@秋叶抚风
可以跟到源码里去看一看
原理就是遍历GridView,然后找Cell里的Control
取不到的原因可能有:传进去的GridView无值,columnIndex指定错误
@Stone2009
:)
同样,可以跟到源代码里看一下,以便分析原因
楼主你好,借地方问一下有关GridView遍历取值的问题
我是在GridView的列里转换成模版,放了几列的CheckBox,原始值是空,运行的时候,随意选择几个CheckBox,然后在后台里处理,但是遍历CheckBox的值,怎么都是False,没有一个是True的。最奇怪的是,如果不是在运行时选择CheckBox,而是在设置原始值时设为True,那么,同样的代码就能取到True。
代码遍历代码如下:
foreach (GridViewRow gvrow in GridView1.Rows)
{
if (gvrow.RowType == DataControlRowType.DataRow)
{
Label lb = (Label)gvrow.FindControl("Label3");
CheckBox cb1 = (CheckBox)gvrow.Cells[1].FindControl("CheckBoxShow");
CheckBox cb2 = (CheckBox)gvrow.FindControl("CheckBoxAdd");
CheckBox cb3 = (CheckBox)gvrow.FindControl("CheckBoxUpdate");
CheckBox cb4 = (CheckBox)gvrow.FindControl("CheckBoxDel");
CheckBox cb5 = (CheckBox)gvrow.FindControl("CheckBoxQuery");
}
}
@lll
看看遍历之前是否重新绑定数据了,如果遍历之前就绑定数据,那得到结果肯定不是客户端传过来的数据
有五列数据,第一列是绑定数据表出来的数据,后面四列都是CheckBox的列。第一列数据是在页面绑定的,这样会有问题吗?但是问题依旧
问题已解决,多谢兄台提醒,仔细检查了下代码,确实是在遍历前有过执行数据绑定。但为什么这样呢?如果兄台有空,望解答一二。
@lll
:)
绑定的话,那GridView自然是你绑定的数据,客户端所做的操作自然就给冲掉了
@60楼 @61楼 @62楼……
根据以上楼所说:
我在60楼所说的问题,应该是在页面中绑定数据造成的。提交的时候,数据再绑定,然后执行List<DataKey> GetCheckedDataKey(GridView gv, int columnIndex) 就取不到原来选择的数据了。
恍然大悟啊^_^
为什么VS2008中用你上面的演示代码会显示 不具有<CheckboxAlls>的公共属性啊
@小菜lllllllll
:)
那是之前测试版的了
正式版的是CascadeCheckboxes
有用过这个控件的朋友请指教,这个方法如何使用?
List<DataKey> GetCheckedDataKey(GridView gv, int columnIndex)
能否详细说说,小弟新手!
@abis
嗯。。。
获取gridview的checkbox所在列(columnIndex)所选中的行的DataKey的集合
楼主啊,这个控件为什么用后台代码绑定的时候,就取不到。。选中行的dataKey值呢,跟踪进去显示
public static List<DataKey> GetCheckedDataKey(GridView gv, int columnIndex)
{
}
gv.rows.count 为零。。用datasource绑定是可以的。。为什么啊?。。我只是需要用楼主你的控件中的固定行和列的功能。。。
这个控件现在用后台代码绑定数据的时候,只要是服务器事件,都需要再次绑定才能取到行。。BindGrid()方法放在 if(!Page.IspostBack)中不行,行都为零。。楼主能否抽点小空把它弄一下。我想跟我一样,碰到这个问题的人应该很多吧。。
@youngjunzhou
具体的我也不太记得了
现在我已经不再维护这个项目了,都有源代码的,如果需要的话可以试着自行修改一下