好大一棵树,新春的祝福(二):功能节点的数据结构和页面展示

目录

          1、n级分类的数据结构

          2、我的树的数据结构和页面展现

          3、在权限方面的应用

 

 

     上一篇说了一下基本的n级分类的数据结构,最后提出了几个缺点,但是却没有给出修改方法,所以呢现在继续。

  

     1、数据结构

     在原有的基础上,把noteID改成FunctionID,去掉code字段,增加三个字段。

     NoteLevel :表示第几级的节点,可以和css配合,“美化”显示效果。
     ParentIDPath: 父节点的路径,用于找到一个节点的子节点和子子节点(及所有子节点)。也可以找到一个节点的所有父节点。
     OrderID :所有节点的总排序,大家一起来排序,一个SQL语句就可以提取出来直接绑定控件,而不需要在使用递归了。

     由于用功能节点作为例子,所以再增加两个字段

     WebURL: 打开网页的网址
     Target   : 打开网页的目标

 

【表结构的截图】

 

     虽然使用三个字段才实现了原来的一个字段的功能,但是每个字段的分工都很明确,也更“专业”,当然你也可以说这三个都是冗余字段。

     2、提取数据

     由于节点的缩进效果不用空格来占位了,所以这里的提取数据的SQL就简单很多了。

     

SELECT FunctionID, NoteTitle, NoteLevel, ParentIDPath, WebURL, Target FROM Test_Tree2 ORDER BY  OrderID

 【提取数据用的SQL语句】

     还是一条SQL语句,由于OrderID是所有节点的总排序,所以得到记录集之后直接绑定控件就可以了,不需要使用递归。当然这里说的控件不是TreeView,而是Repeater、GridView等。

【使用OrderID字段排序的效果】

     3、如何来显示?(请CSS来帮忙)

     为什么放着好好的 TreeView 不用呢?因为他不是太灵活,不好控制页面的显示,如果美工做得效果太特殊了,那么就不好弄了。

     对于“单列”的树,我习惯使用Repeater来显示,内部采用DIV。而对于“多列”的树,我们可以使用GridView控件。GridView控件的树状结构在下一篇(权限选择)里面来说明。

     使用 Repeater 也是很简单的。

 .aspx里的代码:

<asp:Repeater ID="Rpt" runat="server">
        <ItemTemplate>
            <div id='n<%# (Container.DataItem as DataRowView)["FunctionID"]%>'><%# (Container.DataItem as DataRowView)["noteTitle"]%></div>
        </ItemTemplate>
        </asp:Repeater>

 

.aspx.cs里面的代码:

 

private void BindTree()
        {
            //提取数据
            string sql = "SELECT FunctionID, NoteTitle, NoteLevel, ParentIDPath, WebURL, Target FROM Test_Tree2 ORDER BY  OrderID";
            DataTable dt = dal.RunSqlDataTable(sql);

            Rpt.DataSource = dt;
            Rpt.DataBind();

            输出js脚本需要的js数组#region 输出js脚本需要的js数组
            if (dt.Rows.Count > 0)
            {
                System.Text.StringBuilder str = new System.Text.StringBuilder();

                str.Append("<script language=\"javascript\">var notes = new Array();");
                //打开指定结点的子结点 还未实现功能
                str.Append("var firstID = " + dt.Rows[0][0].ToString() + " ;\r\n");
                str.Append("var lastID = " + dt.Rows[dt.Rows.Count - 1][0].ToString() + " ;\r\n");
                str.Append("var a = notes;\r\n");
                foreach (DataRow dr in dt.Rows)
                {
                    str.Append("a[");
                    str.Append(dr["FunctionID"].ToString());            //FunctionID
                    str.Append("] = new Array('");
                    str.Append(dr["NoteLevel"].ToString());                //noteLevel
                    str.Append("','");
                    str.Append(dr["ParentIDPath"].ToString());                    //path
                    str.Append("','");
                    str.Append(dr["WebURL"].ToString());                //weburl
                    str.Append("','");
                    str.Append(dr["Target"].ToString());                //target
                    str.Append("','");
                    str.Append(dr["NoteLevel"].ToString() == "1" ? "1" : "0");                //isshow
                     str.Append("')\r\n");
                }

                str.Append("</script>");

                Response.Write(str.ToString());
            }
            #endregion
        }

【Repeater的前台和后台的代码】

     这样倒是可以显示出来,但是也太难看了,根本就区分不出来一级节点和二级节点,这样拿出来还不得被骂s。别着急我们可以请css来“美化”一下。

 

     增加了class属性和鼠标跟随和鼠标单击的Repeater的代码:

 <asp:Repeater ID="Rpt" runat="server">
        <ItemTemplate>
            <div style="display:block" id='n<%# (Container.DataItem as DataRowView)["FunctionID"]%>' class='css_Tree<%# (Container.DataItem as DataRowView)["NoteLevel"]%>' onclick="treeClick(this)" onmouseover="treeOver(this)"  onmouseout="treeOut(this)">
            <%# (Container.DataItem as DataRowView)["noteTitle"]%></div>
        </ItemTemplate>
        </asp:Repeater>
    </div>

 

     CSS的代码:

 

.css_Tree1  
{
    PADDING: 3px 1px 1px 10px ; 
    FONT-WEIGHT: bold; 
    FONT-SIZE: 16px; 
    COLOR: #222222;
    LINE-HEIGHT: 150%; 
    HEIGHT: 20px; 
    background-color:#ddddda; 
    
}
    
.css_Tree2  
{
    PADDING: 4px 1px 1px 30px ; 
    FONT-SIZE: 12px; 
    COLOR: #111111;  
    height:18pt; 
    background-color:#f6f6f6; 
}
 

.mySelectTree1
{
    PADDING: 3px 1px 1px 10px ; 
    FONT-WEIGHT: bold; 
    FONT-SIZE: 16px; 
    LINE-HEIGHT: 150%; 
    HEIGHT: 20px; 
     
    border: 0px solid #369;
    background-color: #ddddff;
    color: #000; 
      
}

.mySelectTree2
{
    border: 1px solid #369;
    background-color: #FFFFCF;
    color: #111; 
    PADDING: 4px 1px 1px 30px ; 
     FONT-SIZE: 12px; height:18pt;
}

.myActiveTree2
{
    PADDING: 4px 1px 1px 30px ; 
    FONT-SIZE: 12px; 
    COLOR: #111111;  
    height:18pt; 
    
    border: 1px solid #369;
    background-color: #CBDDEE;
    
    
    
}

 

【css的代码】

 

【效果截图】(好像还是挺难看的)

 

     怎么样?这样可以看得过去了吧。当然我是一点艺术细胞都没有的人,弄出来的css也是很难看,不过没关系,我们可以请专业人士来写出来漂亮的css。

     优点:只要是可以用css表现出来的效果都可以加在这个“树”上面,而所需要做得只是修改一下css文件,而不用改代码。

 

     4、如何展开收拢(js脚本)

     总算是好看了一点,但是现在任何效果都没有哇,至少也得弄出来个展开收拢的效果呀。

     所谓的收拢嘛,其实就是让子节点不可见,让网页里的标签不可见的话,可以使用style="display:none" 来做到,可见的话可以使用style="display:block"。

     我们可以给 div 加一个onclick事件,在事件里面修改子节点的display的值。

     思路很简单,代码也很简单。(代码在上面)

     5、加上鼠标跟随和选中的效果

     这个还是js脚本来实现,给div加上 onclick、onmouseover、 onmouseout 事件,然后在事件里面修改div的Class就可以了。

 

Code
 var oldDiv_Over
        var oldDiv_Active
      
        var oldCss1 
        var oldCss2 
        var oldCss_Over
        
        function treeClick(me)
        {
            var id = me.id;
            id = id.substring(1);
            var path = me.path;
            
            //alert(notes[id][2]);
            if (notes[id][2] == "#")
            {
                //一级节点,展开、收拢子节点。
                if (notes[id][4] == "1")
                {
                    //隐藏子节点
                    
                    ShowNote(id,0);
                    notes[id][4] = "0"
                }
                else
                {
                    //显示子节点
                    ShowNote(id,1);
                    notes[id][4] = "1"
                }    
            }
            else
            {
                //二级节点,打开网页
                var url = notes[id][2] + "?fid=" + notes[id][0] ;
                window.open(url ,notes[id][3]);
                
                if (oldDiv_Active)
                    oldDiv_Active.className = oldCss2 ;
                
                oldDiv_Active = me;
                oldCss2 = me.className;
                me.className = "myActiveTree2";
                
            }
        }
        
        function ShowNote(ParentID,isShow)
        {
            for (i=1;i<=lastID;i++)
            {
                if (notes[i])
                {
                    if (notes[i][0] == "2" )
                    {
                        path = notes[i][1];
                        if (path.indexOf("0," + ParentID) == 0 )
                        {
                            if (isShow == "0")
                                document.getElementById("n" + i).style.display = "none";
                            else
                                document.getElementById("n" + i).style.display = "block";
                        }
                    }
                } 
            }
        }
        
        function treeOver(me)
        {
            oldDiv_Over = me;
            oldCss_Over = me.className;
            
            var id = me.id;
            id = id.substring(1);
            
            if (oldDiv_Over != null && oldDiv_Active != oldDiv_Over)
                if (notes[id][0] == "1")
                    me.className = "mySelectTree1";
                else    
                    me.className = "mySelectTree2";
            
        }
        
        function treeOut(me)
        {
             if (oldDiv_Over != null && oldDiv_Active != oldDiv_Over)
                oldDiv_Over.className = oldCss_Over ;
           
        }

 

     6、小结

     这个功能节点的数据结构是n级的,css样式也可以是n级的,但是js脚本却是按照两级来编写的,为什么呢?因为我觉得功能节点这一块,设置成两级的是比较合理的,客户看起来和操作起来都比较舒服,如果级数多了的话,有一点迷宫的感觉了。

     什么?您说您的项目就是很复杂的,二级的不够必须是三级的,那么怎么实现呢?有两种方法:

     第一种是把一级节点放在上面作为导航;第二种是,把三级节点做成标签的形式。

     如果您的项目三级节点也是不行的,必须是四级的,那么也可以,就是把上面的两种方法和在一起,一级的节点放在上面作为导航栏,二级、三级的“升一级”放在左面的功能节点里,四级节点做成标签的形式。

     什么?四级的还不够,那我也没有什么办法了。

 

 

演示效果,可以单击节点

树状结构的演示

基本的n级分类

加一个“编号”

我的树

功能演示

新闻管理

员工管理

时间: 2024-09-20 15:39:03

好大一棵树,新春的祝福(二):功能节点的数据结构和页面展示的相关文章

好大一棵树,新春的祝福(一):n级分类的数据结构

  目录           1.n级分类的数据结构           2.我的树的数据结构和页面展现           3.在权限方面的应用          快过年了,先给大家拜个早年,祝大家新的一年里多多发财,呵呵.现在做什么都要提前,拜年也提前把.      这个树的结构几年前在csdn里面也发过了一次,现在看看,主体结构居然没有什么变化,用了这么长的时间,自我感觉还是很好用的.而且在这个基础之上把其他的功能也都给联系起来了,比如"通用权限".配置信息等.对,权限是和这个有

海量数据:判断一棵树是否为另一棵树的子树

T1是一棵含有几百万个节点的树,T2含有几百个节点.判断T2是否是T1 的子树. 首先考虑小数据量的情况,可以根据树的前序和中序遍历所得的字符串,来通过判断T2生成的字符串是否是T1字符串的子串,来判断T2是否是T1的子树.假设T1的节点数为N,T2的节点数为M.遍历两棵树算法时间复杂性是O(N + M), 判断字符串是否为另一个字符串的子串的复杂性也是O( N + M)(比如使用KMP算法).所需要的空间也是O(N + M). 这里有一个问题需要注意:对于左节点或者右节点为null的情况,需要

递规删除一整棵树 我自己的想法

  一.树型数据库结构 及 树的一些基础知识 首先我们来看一个简单的应用树-.数据库设计如下图: 表名: testTree 字段:id (主键 自动递增1) username (这个任意了.只是一个数据字段) parentid (父节点的ID值) id username parentid1 A 02 B 13 C 24 D 15 E 26 F 5 如果按树来排列这些数据  应该产生如下状态:A|____B|   |____C|   |____E|        |____F||____D 如果按

ztree异步加载设置isParent:true后没有子节点的父节点循环加载整棵树

问题描述 ztree异步加载设置isParent:true后没有子节点的父节点循环加载整棵树 问下有没有什么解决方案? 解决方案 服务器点判断没有子节点设置isParent为false不就好了? 解决方案二: 初始化setting.async.otherParam = {""zTreeIsLoad"":false}; //加载后 function onAsyncSuccess(event treeId treeNode msg){ var treeObj = $.f

ztree jqu...-求好心人指点。ztree删除一个节点后怎么刷新这棵树

问题描述 求好心人指点.ztree删除一个节点后怎么刷新这棵树 重新异步加载ztree用reAsyncChildNodes方法没有反应呢. 解决方案 1. 重新异步加载 zTree var treeObj = $.fn.zTree.getZTreeObj("tree"); treeObj.reAsyncChildNodes(null, "refresh"); 2. 重新异步加载当前选中的第一个节点 var treeObj = $.fn.zTree.getZTreeO

已知一棵树的前序序列为ABCDEF,后序序列为CEDFBA,则对该树进行层次遍历得到的序列为?

问题描述 已知一棵树的前序序列为ABCDEF,后序序列为CEDFBA,则对该树进行层次遍历得到的序列为? 遇见已知先序后序这类问题如何解决?感觉没有中序很难0.0求大神~! 解决方案 http://www.docin.com/p-633991719.html abcdfe 解决方案二: 这道题和一般题,有一点不一样,一般来说必须要有中序遍历+前序遍历或者后序遍历,这样才能确定唯一的根和,左右子树的未知, 但是这道题直接给的前后序列.....所以无法确定左右子树,,,,,我也很想知道分析方法..

中序遍历递增可以判断一棵树是BST树吗

问题描述 中序遍历递增可以判断一棵树是BST树吗 看到有这种算法,但是还看见有人这是错误的,因为不是BST也会有中序遍历递增的情况,我只想到必须要是前提需要是二叉树,不知道谁能举个例子吗? 解决方案 中序遍历严格递增即可判定就是BST树 解决方案二: 判断一棵树是否BST判断树是否是另外一棵树的子树判断一棵树是否是BST 解决方案三: 请看下面的链接: 1) http://blog.csdn.net/stpeace/article/details/9067029 2) http://blog.c

两棵树之间的节点连线问题

问题描述 哪位大侠可以帮忙实现两棵树之间的节点动态连线功能实现,两棵树最好是对应着展开,急用,给力分!!拜谢!!小弟邮箱lyb863@126.com 解决方案 解决方案二:晕蛋是swing的还是Js得???解决方案三:jshhhhhh

用C#或者.net加载一棵树

问题描述 1.加载一棵树a)数据格式为:单位编号单位名称所在位置备注D总公司北京上地D1分公司1北京海淀D2分公司2上海D11分公司1的研发部...Da分公司10Da1分公司10的研发部b)格式说明:D下面的直属公司有D1,D2,Da;D11,Da1分别为D1和Da的分公司 解决方案 解决方案二:节点是否可移动删除合并,是否无限级?解决方案三:treeview不行吗?解决方案四:用Treeview,动态绑定解决方案五:不是无限级就是上面的简单的要求解决方案六:有没有谁能给出个程序或者算法啊