实现CheckBox的三种选中状态(全选、半选、不选)在GridView中模拟树形的功能
度娘了很多帖子,只说三种状态要用图片替换来做,但没找到有用的例子,被逼自己写了一个
三方控件肯定是很多的,如jstree,可以直接用
由于公司的UDS限制,不能上传图片,只能文字说明了。
就是要在gridview中实现如下效果:一级、二级因为三级没有全部选中而显示半选状态
▣一级 |
▣二级 |
三级1 |
三级2 |
js↓
$(function(){ BindCheckNode(); $("span[name^='lblCheck']").click(checkBoxClick); }); function checkBoxClick() { var isChecked = $(this).attr("class") == "default" ? "checked" : "default"; $(this).attr("class",isChecked); //同步checkbox $(this).next().children().eq(0).attr("checked",isChecked!="default"); var trNode = $(this).parent().parent(); childChange(trNode,isChecked); parentChange(trNode,isChecked); } //数据绑定时,对选中状态的节点做变更,如果有一个子节点没有选中,则为半选中状态 function BindCheckNode() { //判断选中状态的节点的子节点是否全部选中, $("span[name^='lblCheck']").each(function(){ if($(this).attr("class")=="checked") { var curNode = this.parentNode.parentNode; if(!CheckAll(curNode)) { $(this).attr("class","checkHalf"); } } }); } //选中状态判断 function CheckAll(curNode) { var level = parseInt($(curNode).attr("level")); var id = $(curNode).attr("id"); var nextNode = $(curNode).next(); while (nextNode != null && parseInt($(nextNode).attr("level")) > level) { //每个节点都要循环它的所有子节点,判断是否选择 var nextCheck=$(nextNode).children().eq(0).children("span").eq(1); if ($(nextCheck).attr("class") == "default") { return false; } nextNode = $(nextNode).next(); } return true; } //checkbox点击后影响子节点 function childChange(curNode,className) { var level = parseInt($(curNode).attr("level")); var nextNode = $(curNode).next(); //循环子节点 while(nextNode!=null && parseInt($(nextNode).attr("level") ) > level) { var nextCheck=$(nextNode).children().eq(0).children("span:eq(1)"); $(nextCheck).attr("class",className); $(nextCheck).next().children().eq(0).attr("checked",className!="default"); nextNode=$(nextNode).next(); } } //checkbox点击后影响父节点 function parentChange(curNode, className) { var pid = $(curNode).attr("pid"); var parentNode = $("#"+pid); if(!$(parentNode).attr("pid")) return false; var parentSpanCheck=$(parentNode).children().eq(0).children("span").eq(1); var childList = $("tr[pid='"+pid+"']"); var flag = false; var tempNode; $.each(childList, function(i,item){ tempNode = $(item).children().eq(0).children("span").eq(1); if($(tempNode).attr("class") != className) { flag = true; return; } }); if(flag) { $(parentSpanCheck).attr("class", "checkHalf"); } else if(!flag && className == "checked") { $(parentSpanCheck).attr("class", "checked"); } else { $(parentSpanCheck).attr("class", "default"); } var parentSpanCheckClass=$(parentSpanCheck).attr("class"); $(parentSpanCheck).next().children().eq(0).attr("checked",parentSpanCheckClass!="default"); if(pid != "0") changeParentState(parentNode, className); }
css↓ 主要是背景图的移动,图片排列方式为 [全选][未选][半选]
<style type="text/css"> .checked {background-position-x: 0px;} .checkHalf{background-position-x: 23px;} .default{background-position-x: 46px;} </style>
C#前台 ↓ 已将多余的东西删掉,gridview中只有一列,跟上面的table相似,lbl_Space用来增加缩进的,保留原始的checkbox,因为在保存的时候需要遍历整个gridview,不管是后台还是js中修改span的class属性,遍历gridview的时候是获取不到的
<asp:GridView ID="dgResource" OnRowDataBound="dgResource_RowDataBound" DataKeyNames="ResourceID" runat="server" AutoGenerateColumns="False"> <Columns> <asp:TemplateField> <HeaderStyle Wrap="False"></HeaderStyle> <ItemStyle Wrap="False"></ItemStyle> <ItemTemplate> <asp:Label runat="server" ID="lbl_Space" ForeColor="#f5fbff" Text='<%# GetSpaceNameFromLevel(DataBinder.Eval(Container, "DataItem.NameValues[Level]").ToString()) %>'> </asp:Label> <span id="lblCheck" name="lblCheck" runat="server" class="default" style="width: 23px; height: 25px; background-image: url(../../Common/Images/Icons/checkboxButton.jpg);"> </span> <div style="display:none;"> <asp:CheckBox runat="server" ID="chk_Query"></asp:CheckBox> </div> <asp:Label runat="server" Text='<%# DataBinder.Eval(Container, "DataItem.ResourceName") %>'></asp:Label> <asp:HiddenField ID="hfdPID" runat="server" Value='<%# Eval("ParentResourceID") %>' /> <asp:HiddenField ID="hfdLevel" runat="server" Value='<%# Eval("NameValues[Level]") %>' /> </ItemTemplate> </asp:TemplateField> </Columns> </asp:GridView>
.net ↓
protected void dgResource_RowDataBound(object sender, GridViewRowEventArgs e) { if (e.Row.RowType == DataControlRowType.DataRow) { string id = ParamUtil.getstring(dgResource.DataKeys[e.Row.RowIndex]["ResourceID"]); string pid = (e.Row.FindControl("hfdPID") as HiddenField).Value; string level = (e.Row.FindControl("hfdLevel") as HiddenField).Value; string application = (e.Row.FindControl("hfdApplication") as HiddenField).Value; //增加节点的属性 e.Row.Attributes.Add("id", id); e.Row.Attributes.Add("pid", pid); e.Row.Attributes.Add("level", level); } } //点击保存时 for (int i = 0; i < dgResource.Rows.Count; i++) { CheckBox chkQuery = (CheckBox)dgResource.Rows[i].FindControl("chk_Query"); //根据chkQuery的Checked即可获取是否选中,注:半选也算选中 }