建議您 先閱讀 ASP.NET 2.0抽離資料存取 & 連線字串-VB.NET 再來閱讀此文章 ...
之前看過Topcat的一篇文章 ... ASP.NET 2.0 使用資料表動態產生TreeView的樹狀結構
其實 很多時候 ... 都在想~該怎麼寫程式 才能寫的更完美
基於以下兩點 作為改寫的基礎
1.不用 Session 來儲存 DataTable,改用ByRef方式傳遞
2.Root節點需要2個以上
建議您 先閱讀 ASP.NET 2.0抽離資料存取 & 連線字串-VB.NET 再來閱讀此文章 ...
之前看過Topcat的一篇文章 ... ASP.NET 2.0 使用資料表動態產生TreeView的樹狀結構
其實 很多時候 ... 都在想~該怎麼寫程式 才能寫的更完美
基於以下兩點 作為改寫的基礎
1.不用 Session 來儲存 DataTable,改用ByRef方式傳遞
2.Root節點需要2個以上
以下 ... 假設 我有一個資料表 Memu內容資料如下
ID 是 節點的代號,自動編號
ParentID 是 所屬的父節點,如果是0,代表為根節點
Value 節點的 Value 值(同Text)
Order 比較特別 是我故意使用來排列順序的
內容如下
要如何動態產生TreeView呢!! 而且 資料表又這麼複雜 ...
等於 是要做出以下效果
+Root1 --Chile1-1 --Chile1-2 +Root2 --Chile 2-1 --Chile 2-1 +Root3 --Chile 3-1 --Chile 3-2 |
首先呢 在 PageLoad的地方 先宣告一個 MenuTree 再呼叫 GetMenu 以下 VB.NET 寫的
02 Dim Script As New Clib.ScriptClass()
03 Dim MenuTree As New TreeView
04 Dim result As Boolean = Script.GetMenu(MenuTree)
05 If result Then
06 Me.phMenu.Controls.Add(MenuTree)
07 Else
08 Dim lblErrMsg As New Label
09 lblErrMsg.Text = "目前系統忙碌中,請稍後再試!</br>對此造成的不便,敬請見諒~ "
10 Me.phMenu.Controls.Add(lblErrMsg)
11 End If
12 End Sub
我在頁面上擺了一個 PlaceHolder 取名叫做 phMenu
因為 我把GetMenu這個方法抽離網頁 ... 另外放在一個 Clib的命名空間裡面 ...
所以 在第二行的地方 宣告他 在實體化
第四行 呼叫GetMenu 把MenuTree 當作參考 傳過去... 然後用一個result 傳回是否建立成功
以下 ~ C#寫的 GetMenu...(請不要打我= =、現在流行雙語教學咩)
02 {
03 MenuTree = new TreeView();
04 DAL.objData oData = new DAL.objData();
05 string SqlTxt = "SELECT * FROM Menu ORDER BY Order";
06 DataTable dt = new DataTable();
07 bool result = false;
08 if (oData.SqlSelectQuery(ref SqlTxt,ref dt))
09 result = AddRoot(ref MenuTree,ref dt);
10 if (result)
11 {
12 MenuTree.ImageSet = TreeViewImageSet.Custom;
13 MenuTree.NodeIndent = 0;
14 return true;
15 }
16 else
17 {
18 return false;
19 }
20 }
行數解說
3-->把 MenuTree 實體化 ...
4--> 宣告oData 把 上一篇所寫的資料存取層實體化 ...
5->宣告一個SqlTxt 存放 SQL敘述 順便把連SQL一起給他吧 ...
6->宣告一個 dt 順便實體化成一個新的DataTable
7->宣告一個 result 儲存 是否成功的狀態
8~9 因為objData 的SqlSelectQuery 會傳回一個 True / False(成功/失敗) 所以剛好用它來處理以下的步驟
成功的話 呼叫AddRoot 把MenuTree和DT 用 Ref 的方式傳遞過去 ...傳回成功/失敗(迷知音:應該~應該~比較省記憶體吧!?)
失敗的話就 ...不做了...(因為有錯ˇˇ 當然不能繼續 ...)
10~依照result 判斷 是不是成功建置出一個TreeView ...
成功的話 傳回成功 失敗的話 傳回失敗 ...
再來是 AddRoot的方法
02 {
03 try
04 {
05 int tmpNodeID;
06 DataRow[] rows = dt.Select("ParentID = 0");
07 if (rows.GetUpperBound(0) >= 0)
08 {
09 TreeNode NewNode;
10 bool rc;
11 foreach (DataRow row in rows)
12 {
13 NewNode = new TreeNode();
14 tmpNodeID = int.Parse(row[0].ToString());
15 NewNode.Text = row[2].ToString();
16
17 MenuTree.Nodes.Add(NewNode);
18
19 rc = AddNodes(ref NewNode, tmpNodeID,ref dt);
20 }
21 }
22 rows = null;
23 return true;
24 }
25 catch
26 {
27 return false;
28 }
29 }
5- 宣告一個tmpNodeID 來存放該節點代號
6- 宣告 rows 來存放 dt.Select出來的結果(因為這邊是要加入根節點,所以ParentID=0
7-21 如果 Select出來有結果 ... 就做以下內容
9-宣告一個 NewNode 用來暫存 新節點的值
10- 宣告一個 rc 用來確定 ...有沒有建立成功(迷之音:好像也沒有用到他 ...)
13-把NewNode實體化!
14-把資料欄位 ID 存入tmpNodeID (因為 ...我懶的打中文 ...直接用INDEX代替) 當然 缺少不了形態轉換= =、(這樣轉 不知道會不會比較快!?還是比較慢!? 不管ˋˊ 我堅持這樣快)
15-把資料欄位 Value 丟進 NewNode的Text裡面(當然 你要丟到Value也可以 隨你高興) 請自由發揮
17-寫入ROOT節點
19-呼叫AddNodes 用來加入子節點的方法 一樣用參考記憶體位址的方式 傳節點過去,再來傳 節點的代號,再來傳DT
22-告訴.net rows這個不要了 可以回收了 ...(為啥我要講這麼詳細= =、)
23-傳回成功訊息!
27-失敗的話 傳回失敗訊息
以下是AddNodes的方法
02 {
03 try
04 {
05 int tmpNodeID;
06 DataRow[] rows = dt.Select("ParentID = " + PID.ToString());
07 if (rows.GetUpperBound(0) >= 0)
08 {
09 TreeNode NewNode;
10 bool rc;
11 foreach (DataRow row in rows)
12 {
13 NewNode = new TreeNode();
14 tmpNodeID = int.Parse(row[0].ToString());
15 NewNode.Text = row[2].ToString();
16
17 tNode.ChildNodes.Add(NewNode);
18
19 rc = AddNodes(ref NewNode, tmpNodeID,ref dt);
20 }
21 }
22 rows = null;
23
24 return true;
25 }
26 catch
27 {
28 return false;
29 }
30 }
重複的上面的 不用說了 ...
這邊不同的是
第六行--> 用傳進來的節點代號 篩選出該節點的子節點 ...
然後 ...然後 ...就完成囉~~~
以上 ... C# & VB.NET 混合版 ...
希望能跟大家交流交流 ...
End
Phoenix 8/5