近段时间公司的一套系统开发时用到了Asp.net自带的TreeView控件,经过几天的努力,把一些遇到的问题和解决方法写下,方便以后查找。
TreeView 控件用于在树结构中显示分层数据,例如目录或文件目录。TreeNode表示树的节点信息。填充节点有三个方式,一是静态数据,即在页面上使用标签<asp:TreeNode>。第二种是数据绑定,TreeView可以绑定到实现 IHierarchicalDataSource 接口的任意数据源控件。重点介绍的是第三种,动态数据填充,也是比较常用的,因为无论是静态数据还是数据绑定,都是一次性将节点填充完成,可能会返回大量数据,同时,如果要显示的信息取决于运行时的所获取的信息,就只有通过动态填充节点了。
使TreeView控件支持动态节点填充,首先将节点的属性PopulateOnDemand设置为true,并且必须定义一个事件处理方法,它包含 TreeNodePopulate 事件所用的填充节点的逻辑。
关于节点TreeNode,Text表示节点显示的文字,Value表示节点的值,可以用来存储跟节点有关的任何值,回发时使用;ValuePath表示从根节点到当前节点的路径,由分隔符连接的节点值(下面会用到);NavigateUrl表示节点链接的地址,SelectAction表示点击节点时的动作,有两个选择,Expand打开节点,Select选中节点。生成的Html是一个<a>标签,如果想自定义一个onclick事件,可以设置节点的Text等于类似<span id='' onclick=''></span>.
当节点填充完成后,如你在浏览器中打开一个节点,第一次打开时,会触发服务器的TreeNodePopulate事件,事件逻辑填充子节点。然后关闭该节点,第二次打开该节点时,就不会回发到服务器了,相当于刚才的关闭只是暂时隐藏了子节点,而第二次打开时,再把子节点设置为显示。(以上只是我的理解,希望不要误导您。具体是如何,没有去深究)。但是如果此时用户插入了新的数据到刚才打开的节点下面,用户想要看到这个新的节点,靠关闭再打开父节点是不管用的,上面已经说了,只有第一次打开节点时才会触发节点填充事件。其中的一个解决方案是把这个节点的子节点清空,然后手动填充子节点。问题是如何找到这个新添加的节点(还没有添加到树上)的父节点。这就用到了上面提到的ValuePath属性,根据具体的业务逻辑,肯定可以得到新添加节点的ValuePath值,我们知道ValuePath表示的是从根节点到当前节点的路径,也就是说得到ValuePath的值,也就得到了到达该节点的路径上所有的节点。用类似于下面的算法
1 TreeView locateTree = this.locateTreeInfo.TreeView1; 2 char[] spitChar = new char[] { '/' }; 3 string[] nodeValues = valuePath.Split(spitChar); 4 int count = nodeValues.Length; 5 string iValue = string.Empty; 6 for (int iLoop = 0; iLoop < count; iLoop++) 7 { 8 iValue = iLoop == 0 ? nodeValues[iLoop] : iValue + "/" + nodeValues[iLoop]; 9 node = locateTree.FindNode(iValue); 10 if (node == null) 11 { 12 break; 13 } 14 else 15 { 16 if (iLoop == count - 1) break; 17 node.Expand(); 18 } 19 }
一层层打开节点,并最终找到目标节点。
可以看出,微软的服务器控件封装了很多东西,但也带来了性能的影响,替换的解决方案是javascript+ajax,这就要求编写更多的s代码了。