逐步解說:顯示 TreeView 控制項中的階層式資料
更新:2007 年 11 月
ASP.NET TreeView 控制項設計用於以階層式結構向使用者顯示資料。使用者可開啟個別節點,這些節點因此可包含子節點。TreeView 控制項適合用於顯示 XML 資料,但可用於以階層架構表示的任何資料。這個逐步解說會示範使用 TreeView 控制項的基本概念,以及顯示階層式資料的各種方式。
逐步解說將說明的工作包括:
必要條件
若要完成這個逐步解說,您必須要有:
Microsoft Visual Web Developer (Visual Studio)。
Microsoft Data Access Components (MDAC) 2.7 (含) 以後版本。
如果使用的是 Microsoft Windows XP 或 Windows Server 2003,您就會已經有了 MDAC 2.7。不過,如果您使用的是 Microsoft Windows 2000,可能需要升級電腦中所安裝的 MDAC。如需詳細資訊,請參閱 MSDN Library 中的<Microsoft Data Access Components (MDAC) Installation>。
存取 SQL Server Northwind 資料庫。如需下載並安裝 SQL Server 範例 Northwind 資料庫的詳細資訊,請參閱 Microsoft SQL Server 網站上的安裝範例資料庫。
注意事項: 如果您需要如何登入執行 SQL Server 之電腦的相關資訊,請聯繫伺服器管理員。
對 Northwind 資料庫具有存取權限之 SQL Server 帳戶的使用者名稱和密碼 (如果 SQL Server 資料庫與 Web 伺服器不是位於同一電腦上)。
建立網站
依照下列步驟建立新的網站和 Web 網頁。
若要建立檔案系統網站
開啟 Visual Web Developer。
在 [檔案] 功能表上按一下 [新增],然後按一下 [網站]。如果您是使用 Visual Web Developer Express,請在 [檔案] 功能表中按一下 [新網站]。
[新網站] 對話方塊隨即出現。
請在 [Visual Studio 安裝的範本] 下方,按一下 [ASP.NET 網站]。
在 [位置] 方塊中,選取 [檔案系統],並輸入您想要用來保存網站頁面的資料夾名稱。
例如,輸入資料夾名稱 C:\WebSites\HierarchicalData。
在 [語言] 清單中,請按一下您想要操作的程式語言。
按一下 [確定]。
Visual Web Developer 會建立資料夾和命名為 Default.aspx 的新頁面。
建立資料的 XML 檔
藉由遵循這些步驟建立新的 XML 檔。
若要建立 XML 檔
在 [方案總管] 中,以滑鼠右鍵按一下網站,再按 [加入新項目]。
在 [加入新項目] 對話方塊的 [標準範本] 下,按一下 [XML 檔]。
在 [名稱] 方塊中,輸入 Bookstore.xml,然後按一下 [加入]。
Visual Web Developer 會建立新的 Bookstore.xml 檔,並開啟程式碼編輯器。
複製下列 XML 資料,然後將這些資料貼到 Bookstore.xml 檔中,覆寫檔案中原有的內容。
<?xml version="1.0" standalone="yes"?> <bookstore> <genre name="fiction"> <book ISBN="10-000000-001"> <title>The Iliad and The Odyssey</title> <price>12.95</price> <comments> <userComment rating="4"> Best translation I've read. </userComment> <userComment rating="2"> I like other versions better. </userComment> </comments> </book> <book ISBN="10-000000-999"> <title>Anthology of World Literature</title> <price>24.95</price> <comments> <userComment rating="3"> Needs more modern literature. </userComment> <userComment rating="4"> Excellent overview of world literature. </userComment> </comments> </book> </genre> <genre name="nonfiction"> <book ISBN="11-000000-002"> <title>Computer Dictionary</title> <price>24.95</price> <comments> <userComment rating="3">A valuable resource.</userComment> </comments> </book> <book ISBN="11-000000-003"> <title>Cooking on a Budget</title> <price>23.95</price> <comments> <userComment rating="4">Delicious!</userComment> </comments> </book> </genre> </bookstore>
XML 檔包含可從線上 bookstore 取得之書籍的資訊。
儲存 Bookstore.xml 檔案,然後將其關閉。
在 TreeView 控制項中顯示 XML 資料
在本節中,您將使用 TreeView 控制項顯示 XML 資料。若要開始,您可以顯示 XML 資訊,而無需任何特殊組態。
若要顯示 XML 資料
開啟 Default.aspx 網頁,然後切換至 [設計] 檢視。
在 [工具箱] 中,將 [TreeView] 控制項從 [巡覽] 群組拖曳至網頁。
以滑鼠右鍵按一下 [TreeView] 控制項,再按 [顯示智慧標籤]。
在 [TreeView 工作] 功能表的 [選擇資料來源] 下拉式清單中,選取 [新增資料來源]。[資料來源組態精靈] 隨即出現。
在 [應用程式要從何處取得資料] 視窗中,選取 [XML 檔]。保留資料來源的預設 ID。按一下 [確定]。
在 [設定資料來源] 對話方塊的 [資料檔案] 方塊中,輸入 ~/Bookstore.xml,然後按一下 [確定]。
您現在可以測試網頁。
若要測試網頁
按 CTRL+F5 執行頁面。
摺疊後展開控制項中的節點。
根據預設,節點只會顯示 Bookstore.xml 檔中項目的標記 (Tag) 名稱。
您可以藉由建立自訂繫結 (該繫結可讓您指定要向每一個節點顯示 XML 檔的何種資訊),自訂在 TreeView 控制項中顯示的資訊。
若要建立自訂繫結
請在 Default.aspx 網頁上,以滑鼠右鍵按一下 [TreeView] 控制項,再按 [顯示智慧標籤]。
在 [TreeView 工作] 功能表上,按一下 [編輯 TreeNode Databindings]。
[TreeView DataBindings 編輯器] 對話方塊隨即出現。
清除 [自動產生資料繫結] 核取方塊,因為您將定義資料繫結 (Data Binding)。
按一下 [加入] 建立新繫結,然後在 [資料繫結屬性] 下,將 [DataMember] 設為 [bookstore],並將 [文字] 設為 [書籍資訊]。
因為 [Bookstore] 節點是 .xml 檔中的最上層節點,且只在 [TreeView] 控制項中出現一次,所以您要設定繫結以顯示靜態 (Static) 值。
按一下 [加入] 建立第二個繫結,然後在 [資料繫結屬性] 下,將 [DataMember] 設為 [genre],並將 [TextField] 設為 [name]。
如此會指定節點將讀取 .xml 檔中的 <genre> 項目,並將其 name 屬性 (Attribute) 指派給 TextField 屬性 (Property)。
按一下 [加入] 建立書籍的第三個繫結,然後在 [資料繫結屬性] 下,將 [DataMember] 設為 [book],並將 [TextField] 設為 [ISBN]。
按一下 [確定]。
您現在可以測試網頁。
若要測試網頁
按 CTRL+F5 執行頁面。
此時,TreeView 控制項會顯示與您定義之繫結對應的三個層級。這三個層級是標記為 [書籍資訊] 的根節點、類型群組和 ISBN 詳細資訊。
您可以為 XML 檔中的任何項目建立資料繫結,但您只可繫結至項目的屬性、內部文字、項目名稱或項目的值。您無法繫結至任何巢狀項目。若要顯示巢狀項目中的值,請建立那些項目的個別繫結。另一個方法是使用 XSLT 轉換 XML 檔,以便將內部項目轉換成屬性。如需詳細資訊和範例,請參閱 XmlDataSource.TransformFile 屬性。
在 TreeView 控制項中顯示關聯式資料
TreeView 控制項可顯示任何型別的階層式資料,即使資料階層架構是邏輯的 (例如在資料庫中) 而不是實體的 (例如在 XML 檔中)。在本節中,您將使用 TreeView 控制項顯示 Northwind 資料庫之關聯表格中的資料。
若要開始,您要建立執行具有 Northwind 資料庫的 SQL Server 之電腦的連接。
若要建立對 SQL Server 的連接
在 [伺服器總管] 中,以滑鼠右鍵按一下 [資料連接],再按一下 [加入資料連接]。如果您是使用 Visual Web Developer Express,請使用 [資料庫總管]。
[加入連接] 對話方塊就會出現。
如果 [資料來源] 清單未顯示 [Microsoft SQL Server (SqlClient)],請按一下 [變更],然後在 [變更資料來源] 對話方塊中選取 [Microsoft SQL Server]。
如果出現 [選擇資料來源] 頁面,請在 [資料來源] 清單中選取您將使用的資料來源類型。在此逐步解說中,資料來源型別為 Microsoft SQL Server。在 [資料提供者] 清單中,按一下 [.NET Framework Data Provider for SQL Server],然後按一下 [繼續]。
注意事項: 如果在 Visual Web Developer 中看不到 [伺服器總管] 索引標籤,請在 [檢視] 功能表中按一下 [伺服器總管]。如果看不到 [資料庫總管] 索引標籤,請在 [檢視] 功能表中按一下 [資料庫總管]。
在 [加入資料連接] 方塊中,於 [伺服器名稱] 方塊中輸入伺服器名稱。
在 [登入伺服器] 區段中,請選取適用於存取執行中之 SQL Server 資料庫的選項 (整合式安全性或特定 ID 和密碼),且如果有必要,請輸入使用者名稱和密碼。
選取 [儲存我的密碼] 核取方塊。
注意事項: 在實際執行應用程式中,請不要使用 [儲存我的密碼],因為這會將使用者名稱和密碼內嵌在應用程式檔案中。
請在 [選取或輸入資料庫名稱] 底下,輸入 Northwind。
按一下 [測試連接],然後在您確定它有正常運作時,按一下 [確定]。
您的新連接已建立在 [伺服器總管] (或 [資料庫總管]) 中的 [資料連接] 下。
設定 TreeView 控制項顯示資料庫資料
在本節中,您將用資料動態填入 (Populate) 節點。第一層級的節點表示主要資料 (此處為分類)。當使用者按一下節點時,會藉由對擷取分類之產品的資料庫進行查詢,建立該分類的子節點。若要擷取資料,您可以使用資料來源控制項。然而,在這個逐步解說中,您將以程式的方式建立和執行查詢。
若要開始,請建立新網頁和新的 TreeView 控制項。
若要建立新網頁和 TreeView 控制項
將名為 TreeViewDynamic.aspx 的 ASP.NET Web 網頁 (Web Form 網頁) 加入您的網站。
開啟 TreeViewDynamic.aspx 網頁、切換至 [設計] 檢視,然後在 Toolbox 中,將 Label 控制項從 [標準] 群組中拖曳至網頁,並將其命名為 labelStatus。
labelStatus 控制項只用於錯誤報告。
在 [工具箱] 中,將 [TreeView] 控制項從 [巡覽] 群組拖曳至網頁。
以滑鼠右鍵按一下 [TreeView] 控制項,再按 [屬性],然後將 [MaxDataBindDepth] 設為 2。
以滑鼠右鍵按一下 [TreeView] 控制項,再按 [顯示智慧工作],然後在 [TreeView 工作] 功能表上按 [編輯節點]。
在 [TreeView 節點編輯器] 對話方塊中,按一下標記為 [加入根節點] 的圖示,然後在 [屬性] 下,將 [文字] 設為 Product List,並將 [PopulateOnDemand] 設為 true。
按一下 [確定]。
您會建立樹狀結構的最上層節點,其中只包含靜態文字。
若要設定 Web.config 檔
在 [工具箱] 中,將 SqlDataSource 控制項從 [資料] 群組拖曳至網頁。
選取 [SqlDataSource] 控制項,然後按一下 [顯示智慧標籤]。
在 [SqlDataSource 工作] 功能表上,按一下 [設定資料來源]。
[設定資料來源 - SqlDataSource1] 精靈會顯示一個頁面,讓您在其中選擇連接。
在 [您的應用程式應該使用哪個資料連接來連接資料庫?] 方塊中,輸入您在<建立 SQL Server 的連接>中所建立的連接,然後按一下 [下一步]。
精靈會顯示一個頁面,您可以在該頁面中選擇將連接字串 (Connection String) 儲存在組態檔中。在組態檔中儲存連接字串有兩個優點:
這麼做比將它儲存在頁面裡來得安全。
您可以在多個頁面中使用相同的連接字串。
選取 [是,將這個連接儲存為] 核取方塊,然後按 [下一步]。
此精靈會顯示一個頁面,您可以在其中指定要從資料庫擷取哪些資料。
在 [指定資料表或檢視的資料行] 的 [名稱] 方塊中,按一下 [分類]。
在 [資料行] 下方,選取 [CategoryID] 和 [CategoryName] 方塊。
按一下 [下一步]。
按一下 [完成]。
您稍後將在這個逐步解說稍後定義的 RunQuery 方法中使用在 Web.config 檔中建立的連接字串。您將不會使用 SqlDataSource 控制項。
現在,您將加入程式碼,以在使用者按一下節點時填入控制項的子節點。若要動態加入節點,您要建立 TreeNodePopulate 事件的事件處理常式。
若要建立事件處理常式
以滑鼠右鍵按一下 [TreeView] 控制項,然後在 [屬性] 中按 [事件] 圖示。
按兩下 TreeNodePopulate 事件的方塊。
將 Visual Web Developer 切換至 [原始碼] 檢視。
將下列以粗體顯示的程式碼加入至處理常式:
Protected Sub TreeView1_TreeNodePopulate(ByVal sender As Object, _ ByVal e As System.Web.UI.WebControls.TreeNodeEventArgs) _ Handles TreeView1.TreeNodePopulate If e.Node.ChildNodes.Count = 0 Then Select Case e.Node.Depth Case 0 PopulateCategories(e.Node) Case 1 PopulateProducts(e.Node) End Select End If End Sub
protected void TreeView1_TreeNodePopulate( object sender, TreeNodeEventArgs e) { if (e.Node.ChildNodes.Count == 0) { switch (e.Node.Depth) { case 0: PopulateCategories(e.Node); break; case 1: PopulateProducts(e.Node); break; } } }
當使用者按一下以開啟節點時,會呼叫此程式碼。因為您想要在樹狀結構的不同層級顯示不同的資料,所以必須判斷使用者按一下的節點深度,然後於該層級適當地填入節點。在這個逐步解說中,如果使用者按一下根節點 (深度 0),則會呼叫 PopulateCategories 方法。如果使用者按一下分類名稱 (深度 1),則會呼叫 PopulateProducts 方法。上述方法會在下一節中顯示。
TreeNodeEventArgs 物件會以程式的方式存取目前節點。若要填入節點,您要將項目加入節點。在範例程式碼中,會將節點傳遞至加入子節點的方法。
從資料庫讀取節點資料
在每一個節點中顯示的資訊都來自資料庫。您必須撰寫程式碼,以執行資料庫查詢、讀取資料錄,並為每一個資料錄建立節點。這個逐步解說會假設您是在使用 SQL Server Northwind 範例資料庫,因此您必須從 System.Data.SqlClient 命名空間使用 ADO.NET 物件。
對於節點的第一層級 (層級 0),您將顯示所有可用分類的清單。您所建立的程式碼會呼叫您稍後將會在逐步解說中建立的 RunQuery 方法。
若要加入所有分類的節點
切換至原始碼檢視。
如果您是在使用單一檔案網頁,則會將下列指示詞加入字碼頁 (Code Page) 的頂端。
<%@ Import Namespace="System.Data" %> <%@ Import Namespace="System.Data.SqlClient" %>
匯入命名空間會讓撰寫您所需要的程式碼更加容易。
如果您是在使用程式碼後置 (Code-Behind) 網頁,請切換至程式碼後置網頁 (TreeViewDynamic.aspx.vb 或 TreeViewDynamic.aspx.cs),並將下列數行程式碼加入類別宣告外之程式碼檔的頂端。
Imports System.Data Imports System.Data.SqlClient
using System.Data; using System.Data.SqlClient;
確保網頁仍處於 [原始碼] 檢視中。
將下列方法加入網頁程式碼。
Sub PopulateCategories(ByVal node As TreeNode) Dim sqlQuery As New SqlCommand( _ "Select CategoryName, CategoryID From Categories") Dim ResultSet As DataSet ResultSet = RunQuery(sqlQuery) If ResultSet.Tables.Count > 0 Then Dim row As DataRow For Each row In ResultSet.Tables(0).Rows Dim NewNode As TreeNode = New _ TreeNode(row("CategoryName").ToString(), _ row("CategoryID").ToString()) NewNode.PopulateOnDemand = True NewNode.SelectAction = TreeNodeSelectAction.Expand node.ChildNodes.Add(NewNode) Next End If End Sub
void PopulateCategories(TreeNode node) { SqlCommand sqlQuery = new SqlCommand( "Select CategoryName, CategoryID From Categories"); DataSet resultSet; resultSet = RunQuery(sqlQuery); if (resultSet.Tables.Count > 0) { foreach (DataRow row in resultSet.Tables[0].Rows) { TreeNode NewNode = new TreeNode(row["CategoryName"].ToString(), row["CategoryID"].ToString()); NewNode.PopulateOnDemand = true; NewNode.SelectAction = TreeNodeSelectAction.Expand; node.ChildNodes.Add(NewNode); } } }
該程式碼會建立封裝查詢文字的 SqlCommand 物件。它會將物件傳遞至會執行資料庫查詢並傳回 DataSet 物件的方法 (您將會撰寫該方法)。然後,該程式碼會在 DataSet 物件的資料錄中執行迴圈 (Loop),並為每一個資料錄建立新節點,同時以資料庫資訊設定節點的文字和值。然後,該程式碼會將每一個節點的 PopulateOnDemand 屬性設為 true,以便在按一下節點時,節點會引發其 TreeNodePopulate 事件。設定 SelectAction 屬性,讓節點根據預設處於展開狀態。
節點的第二層級將顯示每一個分類的產品。因此,填入產品節點會需要參數型查詢,以便您可以為目前分類擷取產品,並適當地填入子節點。
若要加入產品的節點
將下列方法加入網頁程式碼。
Sub PopulateProducts(ByVal node As TreeNode) Dim sqlQuery As New SqlCommand sqlQuery.CommandText = "Select ProductName From Products " & _ " Where CategoryID = @categoryid" sqlQuery.Parameters.Add("@categoryid", SqlDbType.Int).Value = _ node.Value Dim ResultSet As DataSet = RunQuery(sqlQuery) If ResultSet.Tables.Count > 0 Then Dim row As DataRow For Each row In ResultSet.Tables(0).Rows Dim NewNode As TreeNode = New _ TreeNode(row("ProductName").ToString()) NewNode.PopulateOnDemand = False NewNode.SelectAction = TreeNodeSelectAction.None node.ChildNodes.Add(NewNode) Next End If End Sub
void PopulateProducts(TreeNode node) { SqlCommand sqlQuery = new SqlCommand(); sqlQuery.CommandText = "Select ProductName From Products " + " Where CategoryID = @categoryid"; sqlQuery.Parameters.Add("@categoryid", SqlDbType.Int).Value = node.Value; DataSet ResultSet = RunQuery(sqlQuery); if (ResultSet.Tables.Count > 0) { foreach (DataRow row in ResultSet.Tables[0].Rows) { TreeNode NewNode = new TreeNode(row["ProductName"].ToString()); NewNode.PopulateOnDemand = false; NewNode.SelectAction = TreeNodeSelectAction.None; node.ChildNodes.Add(NewNode); } } }
此程式碼與用於填入分類節點的程式碼類似。其中一點不同之處在於,設定 SqlCommand 物件時,會使用在執行階段以使用者已按一下的節點 (也就是已選取的分類) 之值設定的參數。另一點區別是,會將 PopulateOnDemand 屬性設為 false。如此在顯示產品節點時不顯示展開按鈕。這是十分必要的,因為這些產品下並沒有其他節點。
最後一步是建立執行查詢和傳回資料集的方法。
若要執行查詢
將下列副程式加入網頁。
Function RunQuery(ByVal sqlQuery As SqlCommand) As DataSet Dim connectionString As String connectionString = _ ConfigurationManager.ConnectionStrings _ ("NorthwindConnectionString").ConnectionString Dim dbConnection As New SqlConnection dbConnection.ConnectionString = connectionString Dim dbAdapter As New SqlDataAdapter dbAdapter.SelectCommand = sqlQuery sqlQuery.Connection = dbConnection Dim resultsDataSet As DataSet = New DataSet Try dbAdapter.Fill(resultsDataSet) Catch ex As Exception labelStatus.Text = "Unable to connect to SQL Server." End Try Return resultsDataSet End Function
private DataSet RunQuery(SqlCommand sqlQuery) { string connectionString = ConfigurationManager.ConnectionStrings ["NorthwindConnectionString"].ConnectionString; SqlConnection DBConnection = new SqlConnection(connectionString); SqlDataAdapter dbAdapter = new SqlDataAdapter(); dbAdapter.SelectCommand = sqlQuery; sqlQuery.Connection = DBConnection; DataSet resultsDataSet = new DataSet(); try { dbAdapter.Fill(resultsDataSet); } catch { labelStatus.Text = "Unable to connect to SQL Server."; } return resultsDataSet; }
此程式碼會基於傳遞至它的 SqlCommand 物件建立資料配接器 (Adapter)。然後,它會用該配接器建立和填入資料集。
您現在可以測試網頁。
若要測試網頁
按 CTRL+F5 執行頁面。
TreeView 控制項會顯示分類和產品清單。
按一下分類,確認它會摺疊和展開以為每一個分類顯示產品清單。
後續步驟
這個逐步解說同時使用階層式 XML 資料和關聯資料庫填入 TreeView 控制項。您可以使用 TreeView 控制項,將網站巡覽資訊和 XML 資料用做表格式 (清單) 資料。
如需網站巡覽的詳細資訊,請參閱逐步解說:將網站巡覽加入至網站中。
如需使用 XML 資料的詳細資訊,請參閱逐步解說:建立可以顯示 XML 資料的 Web 網頁。