既然是动态的载入数据的TreeView,那么服务器端的数据也同时应该以一种树型结构来保存。通过客户端发送节点标识,返回该节点下的子节点数据从而动态生成子节点。下面是一个模拟文件夹数据存放结构的服务器端数据获取示例。
既然是动态的载入数据的TreeView,那么服务器端的数据也同时应该以一种树型结构来保存。通过客户端发送节点标识,返回该节点下的子节点数据从而动态生成子节点。下面是一个模拟文件夹数据存放结构的服务器端数据获取示例。
我们设计这样一张数据库表来存放文件夹数据结构:
CREATE TABLE [T_202_118_224_132] (
[DirIndex] [int] NOT NULL ,
[Name] [varchar] (256) COLLATE Chinese_PRC_CI_AS NOT NULL ,
[Size] [int] NOT NULL ,
[Date] [char] (12) COLLATE Chinese_PRC_CI_AS NOT NULL ,
[FatherID] [int] NOT NULL ,
[ID] [int] IDENTITY (1, 1) NOT NULL
) ON [PRIMARY]
// 实际上上面数据来之于存放在数据库中的一个FTP服务器的目录结构信息
数据库表预览如下:
DirIndex |
Name |
Size |
Date |
FatherID |
ID |
1 |
Movie |
-1 |
Mar 29 07:23 |
0 |
1 |
2 |
DV作品 |
-1 |
Mar 22 10:28 |
1 |
2 |
3 |
xjtu我的黄金时代-vivi |
-1 |
Mar 22 10:29 |
2 |
3 |
-1 |
MyGoldenAgeA.rm |
1.52E+08 |
Mar 14 15:49 |
3 |
4 |
-1 |
MyGoldenAgeB.rm |
1.38E+08 |
Mar 14 15:49 |
3 |
5 |
-1 |
花絮.rm |
65196399 |
Mar 14 15:49 |
3 |
6 |
4 |
夏日勇气 |
-1 |
Mar 22 10:28 |
2 |
7 |
-1 |
夏日勇气.rm |
1.91E+08 |
Mar 14 20:31 |
4 |
8 |
5 |
大陆 |
-1 |
Apr 2 02:01 |
1 |
9 |
6 |
爱情麻辣烫 |
-1 |
Mar 22 10:28 |
5 |
10 |
-1 |
001.rm |
1.07E+08 |
Mar 15 08:35 |
6 |
11 |
-1 |
002.rm |
72386955 |
Mar 15 08:42 |
6 |
12 |
7 |
大鸿米店-leonado |
-1 |
Mar 29 10:07 |
5 |
13 |
-1 |
01.rm |
1.59E+08 |
Mar 29 10:08 |
7 |
14 |
-1 |
02.rm |
91197989 |
Mar 29 10:08 |
7 |
15 |
... |
... |
... |
... |
... |
... |
这里ID是数据库主键,我们将其作为TreeNode的标识,在展开一个TreeNode时,向服务器发送这个标识,服务器返回TreeNode的子节点信息。关于这个返回的数据格式,为了便于客户端处理,我们把子节点信息以一个二维数组的方式返回给客户端,这样一来客户端只需要执行eval(data),就可以得到一个存放TreeView子节点的原数据对象。
假如我们使用,
http://localhost/TreeView/GetTreeNodes.aspx?nid=1向服务器请求数据,那么服务器将返回:
[
["1","Movie","-1","Mar 29 07:23"],
["84","Other","-1","Apr 5 14:16 "],
["95","Tv","-1","Apr 2 01:39 "],
["174","incoming","-1","Apr 1 23:37 "],
["-1","welcome.msg","440","Mar 31 12:46"]
] 使用数组的
Literal Syntax特性,我们执行eval(remotedata),就得到了一个JScript的二维数组。
如果我们使用同步xmlhttp来取这段数据,这个返回格式已经非常的精简并且便于使用了。可是如果是以xmlhttp的异步执行方式来展开TreeView的节点,那么为了防止客户端插入子节点出错,我们还需要在返回数据中同时输出被Load节点的标志,以便于在异步回调函数执行时,准确确定子节点的加载位置。所以最后服务器返回的子节点信息格式为:
1$[["1","Movie","-1","Mar 29 07:23"],["84","Other","-1","Apr 5 14:16 "],["95","Tv","-1","Apr 2 01:39 "],["174","incoming","-1","Apr 1 23:37 "],["-1","welcome.msg","440","Mar 31 12:46"]] 开头的$之前数据就是被Load节点的标识,当然放在什么位置随便了,只要便于客户端脚本将其取出就行。如果不返回这个标识,要实现异步动态装载TreeView子节点将会非常的困难,很容易出现节点装载位置错误的问题(我们讲异步装载节点的回调函数时会详细说的)。
附服务器端代码示例:

usings#region usings
using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Data.OleDb;
using System.Drawing;
using System.Text;
using System.Web;
using System.Web.SessionState;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
#endregion

namespace TreeView


{

/**//// <summary>
/// Summary description for GetTreeNodes.
/// </summary>
public class GetTreeNodes : System.Web.UI.Page

{
private void Page_Load(object sender, System.EventArgs e)

{
// Put user code to initialize the page here
}


Web Form Designer generated code#region Web Form Designer generated code
override protected void OnInit(EventArgs e)

{
//
// CODEGEN: This call is required by the ASP.NET Web Form Designer.
//
InitializeComponent();
base.OnInit(e);
}

/**//// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()

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

}
#endregion

public OleDbConnection ConnectToAccess()

{
OleDbConnection conn = new OleDbConnection();
conn.ConnectionString = @"Provider=Microsoft.Jet.OLEDB.4.0;" +
@"Data source=E:\Working\Private\TreeView\T_202_118_224_132.mdb";
try

{
conn.Open();
return conn;
}
catch(Exception exp)

{
Response.Write(@"<h2>Failed to connect to data source</h2>"
+ @"<hr size='1'><pre style='font-family:tahoma;'>"
+ exp.ToString() + @"</pre>");
}
return null;
}

protected override void OnLoad(EventArgs e)

{
base.OnLoad (e);

string strNodeId = Request.Params["NID"];
int nodeId = -1;
try

{
nodeId = int.Parse(strNodeId);
}
catch(Exception exp)

{
Response.Write(@"<h2>Error parameter: strDirIndex</h2>"
+ @"<hr size='1'><pre style='font-family:tahoma;'>"
+ exp.ToString() + @"</pre>");
return;
}

OleDbConnection OleDbConn = this.ConnectToAccess();
if ( OleDbConn != null )

{
OleDbCommand OleDbCmd = new OleDbCommand();
OleDbCmd.Connection = OleDbConn;
string sql = "Select [FatherID] From [T_202_118_224_132] Where (ID = {0})";
OleDbCmd.CommandText = string.Format(sql, nodeId);
object objFatherId = OleDbCmd.ExecuteScalar();
StringBuilder strbMetadata = new StringBuilder();
strbMetadata.Append('[');
if ( !(objFatherId is System.DBNull) )

{
int fatherId = (int)objFatherId;
sql = "Select * From [T_202_118_224_132] where (FatherID = {0})";
OleDbCmd.CommandText = string.Format(sql, fatherId);
OleDbDataReader drDirIndex = OleDbCmd.ExecuteReader();

string format = "[\"
{0}\",\"
{1}\",\"
{2}\",\"
{3}\"],";
while(drDirIndex.Read())

{
strbMetadata.AppendFormat(format, (int)drDirIndex[0],
(string)drDirIndex[1], (int)drDirIndex[2], (string)drDirIndex[3]);
}
if ( strbMetadata[strbMetadata.Length-1] == ',' )

{
strbMetadata.Length = strbMetadata.Length-1;
}
drDirIndex.Close();
drDirIndex = null;
}
strbMetadata.Append(']');
OleDbConn.Close();
OleDbCmd.Dispose();
OleDbCmd = null;
string strMetadata = strbMetadata.ToString();
Response.Write(nodeId + "$" + strMetadata);
}
}
}
} 注意,.aspx文件中除了:

<%
@ Page language="c#" Codebehind="GetTreeNodes.aspx.cs" AutoEventWireup="false" Inherits="TreeView.GetTreeNodes" %>
什么也不要留!!!
to be continued . . .