动态载入数据的无刷新TreeView控件(1)

    上次我介绍过,使用popup窗口来制作无限级菜单。由于当时对于JavaScript的了解比较有限,加之又把主要的精力都focus到popup窗口本身的一些问题上去了,所以关于菜单的设计中还是有很多不合理的地方。后来因为需要又作了一个TreeView控件,不过由于需求变化大,被改得来结构相当的乱了,于是抽空重构一下,并把一些设计步骤记录下来,欢迎大家讨论并提意见。

    虽然使用脚本制作的TreeView已经有很多了,不过对于做自己的产品来说,要使用现成的控件是很困难的。首先要能免费授权,其次需要有自己所期望的所有功能,三需要代码清晰到能很快理解并修改。免费可能是最简的要求了,而功能和可修改性却就不容易了,所以最后自己实现一个反而更省事。微软的Microsoft.Web控件包里有个强大的TreeView,不过遗憾的是那个是后台数据邦定的,Expand或Collapse节点需要doPostBack操作:(。

    既然开始都说了,现成的TreeView很多了,那么这个TreeView就必须站在巨人的肩膀上了。首先图标资源就不用自己弄了,从r.a.d.treeview上弄了一套下来(下载它的一个试用版本,里面有所有的图标,不用在网页里去弄),本来这玩意儿到处都有,只是它太全了,足有10多套各种风格的

    制作这个菜单,最重要的有两点,数据结构和UI表现(当然还有操作,不过这是以前者为基础的)。TreeView的数据结构,其实和Menu那个非常的相似,一个Tree类,一个TreeNode类,然后相互组合嵌套就可以了。只是在显示上需要有个合理的子树缩进,略显比菜单麻烦,因为菜单都是相对Parent菜单条目定位。UI表现使用Table元素来做为菜单整体,每一行TR元素作为一个菜单条目。这都不是难点,而最困难的是子树的层次缩进,从目前我所看到的树控件来讲,都是使用类似递归的方式来生成树的层次线条。而由于我前不久做过一个Menu控件,所以非常希望能像Menu那样,子菜单缩紧只用关心父菜单条目,那样实现起来就简洁多了,于是我设计了这样一种新的菜单UI元素的摆放层次。
  
    R.A.D树控件是使用DIV元素来生成树的UI表现,通过嵌套DIV来实现子树,不过子树缩进做的比较郁闷,居然是用一大堆的图片来当作SPACE(因为用别的东西不好控制宽度)。我实现的TreeView中,每个Tree层次是完整独立的,子树作为一个整体潜入父TreeNode,缩进完全由菜单层次自动维护,就是说每个菜单项生成相同的HTML代码。

    Tree类的结构:

 function Tree(attribute, style)
 {
    
this.Extends(CollectionBase);
    
this.m_Nodes = this.m_InnerArray;

    
this.m_ParentNode = null;
    
this.m_ActiveNode = null;
    
this.m_Element = null;
    
this.m_TreeType = TreeType.Normal;
    
this.m_TreeLevel = 0;
    
this.m_IsEventAttached = false;
    
this.m_Id = __GlobalTreeCache__.NewId();
    __GlobalTreeCache__[
this.m_Id] = this;
   
    
this.m_Attributes = attribute ? attribute : new TreeAttribute();
    
this.m_Styles = style ? style : new TreeStyle();   

    
this.InsertAt = function(node, index)
    {
         
this.base.InsertAt.Call(this, node, index);
         node.m_Tree 
= this;  
    };
       
    
this.toString = function()
    {
        
return '[class Tree]';
    };  
 }

    这个结构中,m_TreeLevel是树的层次数,本来用我这种表格嵌套结构,不需要知道树中的层次也是可以的,可是如果不知道当前树的层次是不是Root层,不能正确地生成节点前的操作提示图标。__GlobalTreeCache__是一个全局Hash Table,原理可以参看Menu的实现第三节,作用是为了快速检索TreeNode,而避免每次都去遍历整棵树。m_Attributes & m_Styles是设置TreeView属性和风格的类,在一个TreeView中只分别保持一份实例。

    TreeNodeBase类的结构(TreeNode的所有和UI相关的内容,在TreeNodeBase中生成):
 function TreeNodeBase(text, action, icon, subtree)
 {
    
this.m_Text = text;
    
this.m_Tooltip = ''; 
    
this.m_Atction = action;
    
if ( subtree )
    {
        subtree.m_ParentNode 
= this;
        this.m_ChildTree = subtree;
    }
    this.m_Tree = null
    
this.m_Icon = null;
    
this.m_IconPath = icon;
   
    
this.m_IsChildExpanded = false;
    
this.m_IsLazyLoad = false;
    
this.m_IsLoaded = false;
    
this.m_Checked = false;
    
this.m_Disabled = false;  
   
    
this.m_Element = null;
      
    
this.toString = function()
    {
        
return '[class TreeNodeBase]';
    };
 }

    这个类比较清楚,每个属性的作用都一目了然,就不多说了。

    下一节讲TreeAttributes和TreeStyle类。

    注:CollectionBaseExtendsCall
    
    To be continued . . .

posted on 2005-03-11 23:33 birdshome 阅读(14133) 评论(10) 编辑 收藏

评论

#1楼  回复 引用   

关注哦,最近刚好要用到一个treeview啊,希望能提供一个完整的方案可以下载哦:)
2005-03-12 23:35 | robaggio[未注册用户]

#2楼  回复 引用   

强烈要求推出一个和资源管理器一样能和listView结合使用的treeview(具有拖放功能)。
2005-03-13 06:33 | GirlSpicy[未注册用户]

#3楼  回复 引用   

如果我需要用到我会考虑的,不过这次可能作不到和ListView整合来向Explorer那样了:<
2005-03-13 13:37 | birdshome

#4楼[楼主]  回复 引用 查看   

@robaggio
我这是一个重构的过程,你可以根据你的需求和你所了解的TreeView开发,提你的意见和建议:)
2005-03-13 16:28 | birdshome      

#5楼  回复 引用   

没什么,前两天想写个这样的东西,被那些烦人的事件逼得我放弃了。如果你写一个,我就不是也可以用了吗?^_^
2005-03-15 00:12 | GirlSpicy[未注册用户]

#6楼  回复 引用   

运用CSS behavior属性,外挂一个htc行为,
运用XML存储数据,
*.htc
var objEnv = this; // 引用该文件的文档对象如:DIV,对其进行数据//绑定,<div style="behavior:url(*.htc);" xmlsrc="*.xml"></div>
var strXMLSrc = this.xmlsrc; // Get data of bound object
var objXMLDOM = new ActiveXObject( "Microsoft.XMLDOM" );
objXMLDOM.async = false;
objXMLDOM.load( strXMLSrc );
建立对象,
节点对象,容器对象,根对象,
根据*.xml的数据,判断每有节点是否有子节点,有的话,将容器和该节点对象进行数据绑定,如:obj.xmlsrc = str_xml_src; // 从XML文件获得str_xml_src,当你点击一个节点时,如果该节点xmlsrc != null && xmlsrc != "" 的话,设置该节点的容器:objContainer.style.behavior="url(该htc文件);",目的是让该容器重载新的xml文件,如此递归,实现动态刷新并显示treeview Control
//该方法的优点在于,减轻浏览器负担,如果用户没有点击treeNode的话,该节点容器为内容为空。test_test@163.com
请勿发垃圾邮件
2005-05-28 02:33 | 6qing88

#7楼  回复 引用   

树的层次线条及缩进表现最麻烦了,本来想自己写一个Tree,弄得很痛苦,而meizz写的那个树的功能又不符自己的要求。

本来打算做一个网址收藏的网站,等用户一上网发现好的网址就添加进去,方便共享。用户按自己的喜好布局网址的排列方式,生成独立的书签页面。其中一个功能就是把Windows中的目录操作方式搬到网上去,用ajax实现后台处理。

无奈web编程修为不够,到现在还只是一个想法。

唉~~~
2006-02-26 05:18 | nameless[未注册用户]

#8楼  回复 引用   

birdshome 实现后能否发一份完整的版本到0x255@163.com ???谢谢!
2006-02-26 05:23 | nameless[未注册用户]

#9楼  回复 引用 查看   

看起来效果还挺不错,能不能发一份完整的代码给我啊,谢谢了
tz_xiong@163.com
2008-05-28 22:12 | Joyaspx      

#10楼  回复 引用 查看   

我是完全初学.对C#跟XML都不是太了解.来公司实习,一开始就是让我做个这玩意,真黑~~~努力实现吧~~~~
2008-12-08 16:13 | 天子      

导航

公告

  原创技术文章和心得,转载必须注明来源"博客园"!
  贴子以"现状"提供,且没有任何担保,同时也没有授予任何权利。
昵称:birdshome
园龄:7年10个月
荣誉:推荐博客
粉丝:73
关注:3

搜索

 

常用链接

我的标签

随笔分类(337)

文章分类(147)

相册

Ex-Colleagues

常用链接

兄弟情深

积分与排名

  • 积分 - 3145044
  • 排名 - 6

最新评论

阅读排行榜

推荐排行榜