既然是动态的载入数据的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 ]
[ 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 " ]
]
[ " 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 " ]
]
如果我们使用同步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
"
]]
附服务器端代码示例:
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);
}
}
}
}
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 . . .