正大互联的结构思想:
序号 字段名 类型 大小 说明
1 ID int 4 主键,自增。
2 parentID int 4 父节点。
3 path nvarchar 100 父节点的集合。
4 noteLevel int 4 层数,从1开始计算。
5 isShow nvarchar 50 第一次填充树的时候,是否显示该节点。true/false
6 OrderID int 4 排序字段。
3 noteTitle nvarchar 100 节点名称。
3 WebUrl nvarchar 100 点击节点时打开的网页。如果是#则不打开网页
3 Target nvarchar 100 打开网页的目标。
这个是在无限分级的表的基础上,改进了一下。有几个字段要特殊说明一下
1、path:拿我的电脑来比喻,比如一个文件a.mp3放在了“c:/myDoc/miusic/”里面,如果 a.mp3 是一个节点的话,那么“c:/myDoc/miusic/”就是 path 。
一级节点的parentID都是0,path 也都是0;其他节点的path 就是 父结点的path + "," + 父节点ID。
设置这个字段的目的是可以一次(避免了递归)找到一个节点的子节点、子子节点……,在收拢节点的时候特别有用。
2、OrderID:为什么只用一次绑定就可以了呢?关键就在这里。一个DIV就是一个节点,那么DIV的先后顺序是由谁来决定的呢?不是parentID,也不是path。而是OrderID。
在显示数的时候,谁排在上面,谁排在下面,完全是由OrderID来决定的,这样只需一次绑定就ok了。
当然,在添加、移动、删除节点上带来了不小的麻烦。但是考虑到维护的次数是很少的,对于树的显示次数来说名可以忽略不计了,所以我觉得这么做是值得的。
3、noteLevel:这个决定了节点的外观,把它加到CSS得名称上面,就可以区分不同级别的节点了。在展开节点的时候也会用到。
其他的就没有什么了。
展开和收拢的效果就交给javascript了
function showme(me){
var myID = me.id.replace("n","");
var Level = notes[myID][0];
var path = notes[myID][1];
var url = notes[myID][2];
var target = notes[myID][3];
var isshow = notes[myID][4];
//判断是否打开网页
if (url != "#"){
if (target =="main")
parent.document.getElementById("frmMain").src= url + "?id=" + myID;
else
window.open(url,target)
}
var tmpNote;
pID = "," +myID+ ",";
for(var i=1;i< notes.length;i++)
{
tmpID = "," + notes[1] + ",";
if (myID != notes[1])
if (tmpID.indexOf(pID) !="-1" )
showDIV(myID,i);
}
if (isshow =="True")
notes[myID][4] ="False"; //notShow
else
notes[myID][4] ="True"; //show
}
function showDIV(parentID,sonID){
var myDIV = document.getElementById("n" + sonID);
var parent = document.getElementById("n" + parentID);
if (notes[parentID][4] == "True" ){
myDIV.style.display = "none"; //notShow
notes[sonID][4] = "False"
}
else{
if (notes[sonID][0] - notes[parentID][0] =="1")
myDIV.style.display="";
}
}
</script>
可以用repeater作为树的容器
我整理后的完整代码
.cs
using
System;
using
System.Collections;
using
System.ComponentModel;
using
System.Data;
using
System.Drawing;
using
System.Web;
using
System.Web.SessionState;
using
System.Web.UI;
using
System.Web.UI.WebControls;
using
System.Web.UI.HtmlControls;
using
System.Configuration;
using
System.Data.SqlClient;
namespace
tree

{

/**//// <summary>
/// WebForm1 的摘要说明。
/// </summary>
public class WebForm1 : System.Web.UI.Page

{
protected System.Web.UI.WebControls.Repeater Repeater1;
DataSet ds = new DataSet();
SqlConnection con = new SqlConnection();
private void Page_Load(object sender, System.EventArgs e)

{
// 在此处放置用户代码以初始化页面
con = new SqlConnection(ConfigurationSettings.AppSettings["Sqlcon"]);
string sql = "select * from office where isdelete=0";
SqlDataAdapter da = new SqlDataAdapter(sql,con);
da.Fill(ds);
this.Repeater1.DataSource = ds.Tables[0].DefaultView;
this.Repeater1.DataBind();

/**/////
Response.Write("<script language=\"javascript\">var notes = new Array();");
Response.Write("var a = notes;\r\n");
foreach(DataRow dr in ds.Tables[0].Rows)

{
Response.Write("a[");
Response.Write(dr["id"].ToString());
Response.Write("] = new Array('");
Response.Write(dr["noteLevel"].ToString());
Response.Write("','");
Response.Write(dr["path"].ToString());
Response.Write("','");
Response.Write(dr["weburl"].ToString());
Response.Write("','");
Response.Write(dr["target"].ToString());
Response.Write("','");
Response.Write(dr["isshow"].ToString());
Response.Write("')\r\n");
}
Response.Write("</script>");
}


Web 窗体设计器生成的代码#region Web 窗体设计器生成的代码
override protected void OnInit(EventArgs e)

{
//
// CODEGEN: 该调用是 ASP.NET Web 窗体设计器所必需的。
//
InitializeComponent();
base.OnInit(e);
}

/**//// <summary>
/// 设计器支持所需的方法 - 不要使用代码编辑器修改
/// 此方法的内容。
/// </summary>
private void InitializeComponent()

{
this.Load += new System.EventHandler(this.Page_Load);

}
#endregion
}
}
.aspx
<
HTML
>
<
HEAD
>
<
title
>
WebForm1
</
title
>
<
meta name
=
"
GENERATOR
"
Content
=
"
Microsoft Visual Studio .NET 7.1
"
>
<
meta name
=
"
CODE_LANGUAGE
"
Content
=
"
C#
"
>
<
meta name
=
"
vs_defaultClientScript
"
content
=
"
JavaScript
"
>
<
meta name
=
"
vs_targetSchema
"
content
=
"
http://schemas.microsoft.com/intellisense/ie5
"
>
<
script language
=
"
javascript
"
>

function showme(me)
{
var myID = me.id.replace("n","");
var Level = notes[myID][0];
var path = notes[myID][1];
var url = notes[myID][2];
var target = notes[myID][3];
var isshow = notes[myID][4];
//判断是否打开网页

if (url != "#")
{
if (target =="main")
parent.document.getElementById("frmMain").src= url + "?id=" + myID;
else
window.open(url,target)
}
var tmpNote;
pID = "," +myID+ ",";
for(var i=1;i< notes.length;i++)

{
tmpID = "," + notes[i][1] + ",";
//找自己的所有子节点
if (tmpID.indexOf(pID) !="-1" )
//window.setTimeout("showDIV("+myID+","+i+")",200);
showDIV(myID,i);
}
//for(var i=1;i< notes.length;i++)
//{
//找父结点的子节点
//if (notes[myID][1] == notes[i][1] && myID != i)
//noneOtherDiv(i);
//}
if (isshow =="True")
notes[myID][4] ="False"; //notShow
else
notes[myID][4] ="True"; //show
}
function noneOtherDiv(parentID)

{
for(var i=1;i< notes.length;i++)

{
//找子节点
if (notes[parentID][1] + "," + parentID == notes[i][1] )

{
var tmp = document.getElementById("n" + i);
tmp.style.display = "none";
notes[i][4] = "False"
}
}
}

function showDIV(parentID,sonID)
{
var myDIV = document.getElementById("n" + sonID);
var parent = document.getElementById("n" + parentID);

if (notes[parentID][4] == "True" )
{
myDIV.style.display = "none"; //notShow
notes[sonID][4] = "False"
}

else
{
if (notes[sonID][0] - notes[parentID][0] =="1")
myDIV.style.display="";
}
}
</
script
>
</
HEAD
>
<
body MS_POSITIONING
=
"
GridLayout
"
>
<
form id
=
"
Form1
"
method
=
"
post
"
runat
=
"
server
"
>
<
TABLE id
=
"
Table1
"
style
=
"
Z-INDEX: 101; LEFT: 144px; WIDTH: 112px; POSITION: absolute; TOP: 72px; HEIGHT: 304px
"
cellSpacing
=
"
1
"
cellPadding
=
"
1
"
width
=
"
112
"
border
=
"
1
"
>
<
TR
>
<
TD colSpan
=
"
3
"
valign
=
top
><
FONT face
=
"
宋体
"
>
<
asp:Repeater id
=
"
Repeater1
"
runat
=
"
server
"
EnableViewState
=
"
False
"
>
<
ItemTemplate
>
<
div id
=
'
n<%#DataBinder.Eval(Container,"DataItem.id")%>
'
onclick
=
"
showme(this)
"
><%
#DataBinder.Eval(Container,
"
DataItem.name
"
)
%></
div
>
</
ItemTemplate
>
</
asp:Repeater
></
FONT
></
TD
>
</
TR
>
</
TABLE
>
</
form
>
</
body
>
</
HTML
>
数据库中的id是自增长的,但要是id的值不是连续的话就会出现问题。