ASP.NET 2.0動態產生TreeView樹狀結構-C# & VB.NET 混合

建議您 先閱讀 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 寫的

01     Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
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...(請不要打我= =、現在流行雙語教學咩)

01         public bool GetMenu(out TreeView MenuTree)  
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的方法

01         private bool AddRoot(ref TreeView MenuTree,ref DataTable dt)  
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的方法

01         private bool AddNodes(ref TreeNode tNode, int PID,ref DataTable dt)  
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