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

简介: var oldDiv_Over var oldDiv_Active var oldCss1 var oldCss2 var oldCss_Over f...

目录

          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()
img_405b18b4b6584ae338e0f6ecaf736533.gifimg_1c53668bcee393edac0d7b3b3daff1ae.gif        
{
            
//提取数据
            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();

img_7a2b9a960ee9a98bfd25d306d55009f8.gifimg_2887d91d0594ef8793c1db92b8a1d545.gif            
输出js脚本需要的js数组#region 输出js脚本需要的js数组
            
if (dt.Rows.Count > 0)
img_2887d91d0594ef8793c1db92b8a1d545.gifimg_7a2b9a960ee9a98bfd25d306d55009f8.gif            
{
                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)
img_2887d91d0594ef8793c1db92b8a1d545.gifimg_7a2b9a960ee9a98bfd25d306d55009f8.gif                
{
                    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就可以了。

 

img_1c53668bcee393edac0d7b3b3daff1ae.gif img_405b18b4b6584ae338e0f6ecaf736533.gif 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级分类
加一个“编号”
我的树
功能演示
新闻管理
员工管理
相关文章
|
1月前
|
算法
数据结构之博弈树搜索(深度优先搜索)
本文介绍了使用深度优先搜索(DFS)算法在二叉树中执行遍历及构建链表的过程。首先定义了二叉树节点`TreeNode`和链表节点`ListNode`的结构体。通过递归函数`dfs`实现了二叉树的深度优先遍历,按预序(根、左、右)输出节点值。接着,通过`buildLinkedList`函数根据DFS遍历的顺序构建了一个单链表,展示了如何将树结构转换为线性结构。最后,讨论了此算法的优点,如实现简单和内存效率高,同时也指出了潜在的内存管理问题,并分析了算法的时间复杂度。
52 0
|
2月前
|
存储 算法 搜索推荐
探索常见数据结构:数组、链表、栈、队列、树和图
探索常见数据结构:数组、链表、栈、队列、树和图
123 64
|
27天前
|
存储 缓存 算法
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式,强调了合理选择数据结构的重要性,并通过案例分析展示了其在实际项目中的应用,旨在帮助读者提升编程能力。
53 5
|
1月前
|
存储 搜索推荐 算法
【数据结构】树型结构详解 + 堆的实现(c语言)(附源码)
本文介绍了树和二叉树的基本概念及结构,重点讲解了堆这一重要的数据结构。堆是一种特殊的完全二叉树,常用于实现优先队列和高效的排序算法(如堆排序)。文章详细描述了堆的性质、存储方式及其实现方法,包括插入、删除和取堆顶数据等操作的具体实现。通过这些内容,读者可以全面了解堆的原理和应用。
87 16
|
1月前
|
算法
数据结构之文件系统模拟(树数据结构)
本文介绍了文件系统模拟及其核心概念,包括树状数据结构、节点结构、文件系统类和相关操作。通过构建虚拟环境,模拟文件的创建、删除、移动、搜索等操作,展示了文件系统的基本功能和性能。代码示例演示了这些操作的具体实现,包括文件和目录的创建、移动和删除。文章还讨论了该算法的优势和局限性,如灵活性高但节点移除效率低等问题。
53 0
|
2月前
|
存储 算法 关系型数据库
数据结构与算法学习二一:多路查找树、二叉树与B树、2-3树、B+树、B*树。(本章为了解基本知识即可,不做代码学习)
这篇文章主要介绍了多路查找树的基本概念,包括二叉树的局限性、多叉树的优化、B树及其变体(如2-3树、B+树、B*树)的特点和应用,旨在帮助读者理解这些数据结构在文件系统和数据库系统中的重要性和效率。
32 0
数据结构与算法学习二一:多路查找树、二叉树与B树、2-3树、B+树、B*树。(本章为了解基本知识即可,不做代码学习)
|
2月前
|
分布式计算 Hadoop Unix
Hadoop-28 ZooKeeper集群 ZNode简介概念和测试 数据结构与监听机制 持久性节点 持久顺序节点 事务ID Watcher机制
Hadoop-28 ZooKeeper集群 ZNode简介概念和测试 数据结构与监听机制 持久性节点 持久顺序节点 事务ID Watcher机制
54 1
|
2月前
|
存储 编译器 C++
【初阶数据结构】掌握二叉树遍历技巧与信息求解:深入解析四种遍历方法及树的结构与统计分析
【初阶数据结构】掌握二叉树遍历技巧与信息求解:深入解析四种遍历方法及树的结构与统计分析
|
2月前
【高阶数据结构】二叉树进阶探秘:AVL树的平衡机制与实现详解(三)
【高阶数据结构】二叉树进阶探秘:AVL树的平衡机制与实现详解
|
2月前
【高阶数据结构】二叉树进阶探秘:AVL树的平衡机制与实现详解(二)
【高阶数据结构】二叉树进阶探秘:AVL树的平衡机制与实现详解