[导入]TreeView的级联选择(上)
在Asp.Net中的TreeView是一个比较好的导航控件,有了它,复杂的脚本就不用写了,可以轻松的展示层次结构的数据,也可以将其作为一个输入控件,从树上选择某个节点,当然这时候,要让每个节点前的CheckBox显示出来,比较讨厌的地方在于选中某个节点后,它的子节点不能自动选中,同样的它的父节点也不会自动选中,当然可以在服务器端代码中编写选中的代码,只不过页面每次选中一个节点,都要提交一次,对客户来说,不是很友好,最好是用脚本来控制前端的内容。
在网上找了许久,解决的办法倒是有,不过太麻烦了,也挺难看的,一气之下,重写。
重写要有个基础,思路主要来自于一篇选中某个节点,然后让这个节点的父节点选中的文章中演化来的。
它的主要思路是在页面加载的时候,将TreeView中的每个CheckBox控件的onclick事件注册给某个脚本方法,在这个脚本方法的内部,利用TreeView生成的客户端代码的层次关系来控制哪些应该选中。
就是它了。
先在一个普通的ASP.Net页面上先放一个TreeView,添些节点,浏览,分析生成的Html代码。
如果一个节点没有子节点,那么在这个节点之下肯定没有一个id为CheckBox的id前缀的div,有点复杂了,比如有个节点的CheckBox的id为“TreeView1n0CheckBox”,如果有子节点,那么一定存在一个id为“TreeView1n0Nodes”的div,在这个div中的table中放的就是子节点。
在页面上加上3个javascript方法:
//看是否应用了样式
//如果没有应用样式,table中应该只有1行,
//如果没有应用样式,table中应该只有1行,
//CheckBox会在这一行中出现
//如果应用了样式,table中应该有3行
//CheckBox一般会在第二行中出现
function HasStyle(tree)
{
var x=document.getElementById(tree).childNodes[0].childNodes[0].childNodes.length;
return parseInt(x-1);
}
//选中子节点
//obj为某个点中的CheckBox
//x为0:没有应用样式,1:应用了样式
function SelectAllChild(obj,x)
{
//获得子节点的id
var childrenId=obj.id.replace("CheckBox","Nodes");
//获得子节点
var temp=document.getElementById(childrenId);
//如果有子节点
if(temp!=null)
{
//获取其中的子节点,目的是找那些TABLE
//因为在Table中有CheckBox
var items=document.getElementById(childrenId).childNodes;
//如果应用了样式,table中应该有3行
//CheckBox一般会在第二行中出现
function HasStyle(tree)
{
var x=document.getElementById(tree).childNodes[0].childNodes[0].childNodes.length;
return parseInt(x-1);
}
//选中子节点
//obj为某个点中的CheckBox
//x为0:没有应用样式,1:应用了样式
function SelectAllChild(obj,x)
{
//获得子节点的id
var childrenId=obj.id.replace("CheckBox","Nodes");
//获得子节点
var temp=document.getElementById(childrenId);
//如果有子节点
if(temp!=null)
{
//获取其中的子节点,目的是找那些TABLE
//因为在Table中有CheckBox
var items=document.getElementById(childrenId).childNodes;
var count=items.length;
for(var i=0;i<count;i++)
{
if(items[i].tagName=='TABLE')
{
//找到tr
var tr=items[i].childNodes[0].childNodes[parseInt(x)];
//找到td集合
var tds=tr.childNodes;
//找到最后一个td
var lastTd=tds[tds.length-1];
//获得最后一个td中的第一个元素,就是checkbox
var input=lastTd.childNodes[0].id;
//设置这个checkbox的状态为父节点的状态
document.getElementById(input).checked=obj.checked;
//接着看这个子节点还有没有孙子节点。
SelectAllChild(document.getElementById(input),parseInt(x));
}
}
}
}
//遍历每个CheckBox,给它们加上onclick处理过程
for(var i=0;i<count;i++)
{
if(items[i].tagName=='TABLE')
{
//找到tr
var tr=items[i].childNodes[0].childNodes[parseInt(x)];
//找到td集合
var tds=tr.childNodes;
//找到最后一个td
var lastTd=tds[tds.length-1];
//获得最后一个td中的第一个元素,就是checkbox
var input=lastTd.childNodes[0].id;
//设置这个checkbox的状态为父节点的状态
document.getElementById(input).checked=obj.checked;
//接着看这个子节点还有没有孙子节点。
SelectAllChild(document.getElementById(input),parseInt(x));
}
}
}
}
//遍历每个CheckBox,给它们加上onclick处理过程
function
AutoSelectHandle(treeID)
{
var x=HasStyle(treeID);
//获得所有的input标记
var objs = document.getElementsByTagName("input");
//遍历
for(var i=0;i<objs.length;i++)
{
//如果是CheckBox
if(objs[i].type=='checkbox')
{
var obj=objs[i];
//如果CheckBox的id中包括TreeView在客户端的id
//那么意味着这个CheckBox是TreeView中的CheckBox
if(obj.id.indexOf(treeID)!=-1)
{
//注册事件处理过程
objs[i].onclick=function(){SelectAllChild(this,parseInt(x));};
}
}
}
}
{
var x=HasStyle(treeID);
//获得所有的input标记
var objs = document.getElementsByTagName("input");
//遍历
for(var i=0;i<objs.length;i++)
{
//如果是CheckBox
if(objs[i].type=='checkbox')
{
var obj=objs[i];
//如果CheckBox的id中包括TreeView在客户端的id
//那么意味着这个CheckBox是TreeView中的CheckBox
if(obj.id.indexOf(treeID)!=-1)
{
//注册事件处理过程
objs[i].onclick=function(){SelectAllChild(this,parseInt(x));};
}
}
}
}
在TreeView的下面加一段:
<script type="text/javascript"
language="javascript">
AutoSelectHandle("<%=TreeView1.ClientID%>");
</script>
AutoSelectHandle("<%=TreeView1.ClientID%>");
</script>
到此,万里长征已经走了第一步,下一步为根据当前节点的状况和兄弟节点的状况来决定父节点的选中状态,这是个好深的坑,刚才是向下走,现在是朝回走。
土鳖扛铁牛。
文章来源:http://blog.sina.com.cn/s/blog_49458c270100c26l.html