正大互联的结构思想:
序号 字段名 类型 大小 说明
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.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 窗体设计器生成的代码
}
}
.aspx
<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>