原因


当前的树控件或多或少存在各种各样的问题,有样式的,有速度的,与IE7兼容性问题的。而且因为没有源码,处理这些问题时非常麻烦。通常,在使用树控件时只需使用很简单的一些功能,收缩/展开,链接等。即然如此,为什么不可以自己实现一个满足这些简单功能的树呢?自已的东西,就算再烂,出现问题时,也知道怎么处理呀。


设计思路


树控件最后解析成HTML代码的时候是什么呢?有的控件是DIV,有的是Table,本人认为用table更好控制。所以我的方案采取直接绘表格的方式实现,至于添加子节点,其实也就是表格中套表格了。


1、直接画Table,每个节点就是表格的一行。


2、每行分为两列,图标为一列,显示文本为一列。


3、第一级节点与子节点分开实现。


4、实现节点可以添加子节点方法。


5、提供点击事件处理接口,具体的点击方法在使用时由用户自己实现。


jquery 手写树形控件 js实现树控件_移动开发



效果演示:

jquery 手写树形控件 js实现树控件_ViewUI_02



类代码


jquery 手写树形控件 js实现树控件_移动开发_03

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.Text;
 
  using 
   System.Text.RegularExpressions;

 
  namespace 
   Shanqian.Component
 
  
 
  {

    public abstract class treenode
    
{
        protected StringBuilder nodestring;
        /**//// <summary>
        /// 节点的HTML代码
        /// </summary>
        public StringBuilder Nodestring
        
{
            get 
{ return nodestring; }
            set 
{ nodestring = value; }
        }
        protected string script;
        /**//// <summary>
        /// 点击节点将触发的事件:JavaScript函数名称
        /// </summary>
        public string Script
        
{
            get 
{ return script; }
            set 
{ script = value; }
        }
        protected string text;
        /**//// <summary>
        /// 节点显示文本
        /// </summary>
        public string Text
        
{
            get 
{ return text; }
            set 
{ text = value; }
        }
        protected string value;
        /**//// <summary>
        /// 节点值
        /// </summary>
        public string Value
        
{
            get 
{ return value; }
            set 
{ this.value = value; }
        }
        protected string imgURL;
        /**//// <summary>
        /// 展开/收缩图标(一般不需要你去用)
        /// </summary>
        public string ImgURL
        
{
            get 
{ return imgURL; }
            set 
{ this.imgURL = value; }
        }

        protected string nodeStyle;
        /**//// <summary>
        /// 样式名称
        /// </summary>
        public string NodeStyle
        
{
            get 
{ return nodeStyle; }
            set 
{ this.nodeStyle = value; }
        }

        protected bool isExpand;
        /**//// <summary>
        /// 是否展开该节点
        /// </summary>
        public bool IsExpand
        
{
            get 
{ return isExpand; }
            set 
{ this.isExpand = value; }
        }

        /**//// <summary>
        /// 在该节点下添加子节点
        /// </summary>
        /// <param name="node"></param>
        public abstract void addChildNode(treenode node);
        /**//// <summary>
        /// 重置节点到初始状态。
        /// </summary>
        public abstract void init();

    }

    public class firstNode : treenode
    
{
        public firstNode()
        
{
            this.ImgURL = "images/c.gif";
        }

        public override void addChildNode(treenode node)
        
{
            if (this.Nodestring == null)
            
{
                this.ImgURL = "images/c.gif";
                init();
            }
            if (node.Nodestring == null)
            
{
                node.init();
            }
            if (node.IsExpand)
            
{
                this.IsExpand = true;
                Regex re = new Regex("style=\"display:none;\"");
                string str = re.Replace(this.Nodestring.ToString(), "style=\"\"", 1);

                Regex reImg = new Regex(this.ImgURL);
                str = reImg.Replace(str, "images/o.gif", 1);

                this.Nodestring.Remove(0, this.Nodestring.Length);
                this.Nodestring.Append(str);
            }
            this.Nodestring.Insert(this.Nodestring.Length - 8, node.Nodestring.ToString());

        }
        public override void init()
        
{
            string strid = System.Guid.NewGuid().ToString().Replace("-", "");
            string strstyle = "";
            if (!this.IsExpand)
            
{            
                strstyle = "display:none;";
            }
            else
            
{
                this.ImgURL = "images/o.gif";
            }
            StringBuilder sb = new StringBuilder(100);
            sb.Append("<table border=\"0\"><tr id=\"" + strid + "\"><td style=\"width:5px\" οnclick=\"imgclick(this);\"><img id=\"img" + strid + "\" src='" + this.ImgURL + "' /></td><td class=\""+this.NodeStyle+"\" οnclick=\"" + this.Script + "\">" + this.Text + "</td></tr></table>");

            sb.Append("<table border=\"0\" cellpadding=\"0\" cellspacing =\"0\" id=\"tb" + strid + "\" style=\"" + strstyle + "\">");

            sb.Append("</table>");
            this.Nodestring = sb;
        }

    }

    public class childNode : treenode
    
{
        public childNode()
        
{
            
            this.ImgURL = "images/e.gif";
            
        }

        public override void addChildNode(treenode node)
        
{
            if (this.Nodestring == null)
            
{
                this.ImgURL = "images/c.gif";
                init();
            }            
            if (node.Nodestring == null)
            
{
                node.init();
            }
            if (node.IsExpand)
            
{
                this.IsExpand = true;
                Regex re = new Regex("style=\"display:none;\"");
                string str = re.Replace(this.Nodestring.ToString(), "style=\"\"", 1);

                Regex reImg = new Regex(this.ImgURL);
                str = reImg.Replace(str, "images/o.gif", 1);

                this.Nodestring.Remove(0, this.Nodestring.Length);
                this.Nodestring.Append(str);
            }
            this.Nodestring.Insert(this.Nodestring.Length - 18, node.Nodestring.ToString());
        }
        public override void init()
        
{
            string strid = System.Guid.NewGuid().ToString().Replace("-", "");
            string strstyle = "";
            if (!this.IsExpand)
            
{
                strstyle = "display:none;";
            }
            else
            
{
                this.ImgURL = "images/o.gif";
            }
            StringBuilder sb = new StringBuilder(100);
            sb.Append("<tr><td style=\"width:10px\"> </td><td>");
            sb.Append("<table border=\"0\"><tr id=\"" + strid + "\"><td style=\"width:5px\" οnclick=\"imgclick(this);\"><img id=\"img" + strid + "\" src='" + this.ImgURL + "' /></td><td class=\"" + this.NodeStyle + "\" οnclick=\"" + this.Script + "\">" + this.Text + "</td></tr></table>");
            sb.Append("<table border=\"0\" cellpadding=\"0\" cellspacing =\"0\" id=\"tb" + strid + "\" style=\"" + strstyle + "\">");

            sb.Append("</table></td></tr>");
            this.Nodestring = sb;
        }
    }
}


代码说明

图标文件:0.gif;e.gif;c.gif放在images文件夹中,在需要用该树的时候加到工程中。这三个图标文件山前是从MSDN帮助中的树控件上下载下来的。

图标的点击事件方法是: imgclick(this),这个方法名已经写死了。山前比较懒不想做得太灵活。够用原则。

该方法就是点击图标实现展开/收缩效果。

方法具体如下:

这个类怎么用呢?我们的设计思想是以直接绘表格的方式绘制树的。绘好之后肯定就是一段HTML代码。如果要请树在界面上显示出来。只需将树的Nodestring输出到界面即可。

function imgclick(obj)
 {
     var ii=obj.parentElement.id;
     var di;
     di = window.document.getElementById("tb"+ii).style.display;
     if(di=="")
     {
         window.document.getElementById("tb"+ii).style.display = "none";
         var img =window.document.getElementById("img"+ii).src;

         if(img.indexOf("images/e.gif")<0)
         {
             window.document.getElementById("img"+ii).src = "images/c.gif";
         }
     }
     else if(di=="none")
     {
         window.document.getElementById("tb"+ii).style.display = "";
         var img =window.document.getElementById("img"+ii).src;
         if(img.indexOf("images/e.gif")<0)
         {
             window.document.getElementById("img"+ii).src = "images/o.gif";
         }
     }
    
 }

给个示例

示例

您可以在Page_load中输出 Nodestring

。也可以重载Rendercontrol方法


jquery 手写树形控件 js实现树控件_移动开发_03

 

总结

protected 
    
  void 
   Page_Load( 
  object 
   sender, EventArgs e)
       
   {        
        
        treenode tnf = new firstNode();        
        tnf.Text = "一级节点一";
        tnf.IsExpand = true;
        tnf.Script = "nodeclick(this);";

        treenode tnc = new childNode();        
        tnc.Text = "二级节点一";        
        tnc.Script = "nodeclick(this);";
        
        treenode tnc2 = new childNode();       
        tnc2.Text = "二级节点二";
        tnc2.Script = "nodeclick(this);";

        treenode tnc3 = new childNode();        
        tnc3.Text = "三级节点一";        
        tnc3.Script = "nodeclick(this);";

        tnc.addChildNode(tnc3);
        tnf.addChildNode(tnc);
        tnf.addChildNode(tnc2);
        this.Response.Write(tnf.Nodestring.ToString());
       
    }  

其中nodeclick(this)的代码你可以写在aspx文件夹中。代码如下:  

 var selectobj;  
 function nodeclick(obj)  
 {  
     var ii=obj.parentElement.id;  
     var di;  
     di = window.document.getElementById("tb"+ii).style.display;  
     if(di=="")  
     {  
         window.document.getElementById("tb"+ii).style.display = "none";  
         var img =window.document.getElementById("img"+ii).src;  

         if(img.indexOf("images/e.gif")<0)  
         {  
             window.document.getElementById("img"+ii).src = "images/c.gif";  
         }  
     }  
     else if(di=="none")  
     {  
         window.document.getElementById("tb"+ii).style.display = "";  
         var img =window.document.getElementById("img"+ii).src;  
         if(img.indexOf("images/e.gif")<0)  
         {  
             window.document.getElementById("img"+ii).src = "images/o.gif";  
         }  
     }  
     if(selectobj!=null)  
     {  
         selectobj.style.backgroundColor = "#FFFFFF";  
     }  
     obj.style.backgroundColor = "#666666";  
     selectobj = obj;  
 }

该类提供了节点的点击事件,而且点击事件的具体方法用户可以随意定制。适用性较强。

而且采用直接绘表格的方式实现,进行样式处理会非常容易,也不会出现与浏览器兼容的问题。