建議您 先閱讀 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 寫的
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...(請不要打我= =、現在流行雙語教學咩)
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的方法
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的方法
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
Protected