上一篇文章我們介紹了樹控件的基本用法,不過都是通過標簽來聲明樹控件的結構,本章我們會詳細講解如何在后台綁定樹控件。
綁定到XmlDocument
下面通過一個簡單的例子來看如何將XmlDocument和樹控件綁定,頁面的標簽結構:
1: <ext:Tree ID="Tree1" Width="500px" EnableArrows="false" EnableLines="false" ShowHeader="true"
2: Title="樹控件(綁定到 XmlDocument)" runat="server">
3: </ext:Tree>
這里有兩個屬性需要注意:
- EnableArrows:是夠啟用箭頭折疊標示,否則是默認的加減折疊標示。
- EnableLines:是否啟用折疊標示之間的連接虛線。
來看下后台的初始化代碼:
1: private void LoadData()
2: {
3: string xmlPath = Server.MapPath("~/tree/databind/website.xml");
4:
5: string xmlContent = String.Empty;
6: using (StreamReader sr = new StreamReader(xmlPath))
7: {
8: xmlContent = sr.ReadToEnd();
9: }
10:
11: XmlDocument xdoc = new XmlDocument();
12: xdoc.LoadXml(xmlContent);
13:
14: Tree1.DataSource = xdoc;
15: Tree1.DataBind();
16: }
這段代碼的邏輯很簡單:
- 獲得需要讀取XML文件的服務器路徑;
- 使用StreamReader來讀取文件的內容;
- 創建XmlDocument實例,並加載XML文件內容;
- 設置樹控件的DataSource為此實例,並調用DataBind執行數據綁定。
最后來看下XML文件的內容和最終的效果截圖:
1: <?xml version="1.0" encoding="utf-8" ?>
2: <Tree>
3: <TreeNode Text="中國" Expanded="true" NodeId="China">
4: <TreeNode Text="河南省" Expanded="true" NodeId="henan">
5: <TreeNode Text="駐馬店市" NodeId="zhumadian" />
6: <TreeNode Text="漯河市" NodeId="luohe" />
7: </TreeNode>
8: // 省略其他節點...
9: </TreeNode>
10: </Tree>
綁定到XmlDataSource
綁定到XmlDataSource簡化了上面的步驟,我們來看一下實現相同功能的示例:
1: <ext:Tree ID="Tree1" Width="500px" EnableArrows="true" EnableSingleExpand="true"
2: ShowHeader="true" Title="樹控件(綁定到 XmlDataSource)" runat="server">
3: </ext:Tree>
4: <asp:XmlDataSource ID="XmlDataSource1" runat="server" DataFile="~/tree/databind/website.xml">
5: </asp:XmlDataSource>
在來看下后台初始化代碼和顯示效果:
1: private void LoadData()
2: {
3: Tree1.DataSource = XmlDataSource1;
4: Tree1.DataBind();
5: }
注意:在ASPX中設置了樹控件的EnableSingleExpand屬性,也就是說同一級目錄只能展開一個節點。
綁定到SiteMap
不知道你有沒有注意到,上面兩個例子XML文件中定義的節點屬性和樹節點的屬性一模一樣,如果不一樣怎么辦?
沒關系,可以為樹控件指定映射關系,用來將XML中定義的節點屬性名稱和樹節點的屬性進行對應,SiteMap就是一個典型例子。
來看一下SiteMap文件:
1: <?xml version="1.0" encoding="utf-8" ?>
2: <siteMap xmlns="http://schemas.microsoft.com/AspNet/SiteMap-File-1.0" >
3: <siteMapNode title="中國" Expanded="true" NodeId="China">
4: <siteMapNode title="河南省" description="河南省省會" Expanded="true" NodeId="henan">
5: <siteMapNode title="駐馬店市" NodeId="zhumadian" />
6: <siteMapNode title="漯河市" NodeId="luohe" />
7: </siteMapNode>
8: // 省略其他節點...
9: </siteMapNode>
10: </siteMap>
其中title, description, url是SiteMap節點標准的屬性名稱,下面我們看下ASPX標簽的定義,看看如何將這些屬性名映射到樹節點的屬性:
1: <ext:Tree ID="Tree1" Width="500px" ShowHeader="true" Title="樹控件(綁定到 SiteMap)" runat="server">
2: <Mappings>
3: <ext:XmlAttributeMapping From="url" To="NavigateUrl" />
4: <ext:XmlAttributeMapping From="title" To="Text" />
5: <ext:XmlAttributeMapping From="description" To="ToolTip" />
6: </Mappings>
7: </ext:Tree>
8: <asp:XmlDataSource ID="XmlDataSource2" runat="server" DataFile="~/tree/databind/Web.sitemap">
9: </asp:XmlDataSource>
看下最終的顯示效果,特別注意“河南省”節點的Tooltip:
綁定到DataTable
在實際項目中,我們可能需要從一個數據表中讀出具有層次結構的數據,比如菜單表中通過ID和ParentID來定義這種結構。
下面我們通過一段代碼來生成類似的DataTable結構:
1: private DataTable CreateDataTable()
2: {
3: DataTable table = new DataTable();
4: DataColumn column1 = new DataColumn("Id", typeof(string));
5: DataColumn column2 = new DataColumn("Text", typeof(String));
6: DataColumn column3 = new DataColumn("ParentId", typeof(string));
7: table.Columns.Add(column1);
8: table.Columns.Add(column2);
9: table.Columns.Add(column3);
10:
11: DataRow row = table.NewRow();
12: row[0] = "china";
13: row[1] = "中國";
14: row[2] = DBNull.Value;
15: table.Rows.Add(row);
16:
17: row = table.NewRow();
18: row[0] = "henan";
19: row[1] = "河南省";
20: row[2] = "china";
21: table.Rows.Add(row);
22:
23: row = table.NewRow();
24: row[0] = "zhumadian";
25: row[1] = "駐馬店市";
26: row[2] = "henan";
27: table.Rows.Add(row);
28:
29: row = table.NewRow();
30: row[0] = "luohe";
31: row[1] = "漯河市";
32: row[2] = "henan";
33: table.Rows.Add(row);
34:
35: // 省略其他節點...
36:
37: return table;
38: }
毫無疑問,這段代碼生成的層次結構如下所示:
當然,這也是我們最終要實現的效果,來看下樹控件的初始化代碼:
1: protected void Page_Load(object sender, EventArgs e)
2: {
3: if (!IsPostBack)
4: {
5: LoadData();
6: }
7: }
8:
9: private void LoadData()
10: {
11: DataTable table = CreateDataTable();
12:
13: DataSet ds = new DataSet();
14: ds.Tables.Add(table);
15: ds.Relations.Add("TreeRelation", ds.Tables[0].Columns["Id"], ds.Tables[0].Columns["ParentId"]);
16:
17: foreach (DataRow row in ds.Tables[0].Rows)
18: {
19: if (row.IsNull("ParentId"))
20: {
21: TreeNode node = new TreeNode();
22: node.Text = row["Text"].ToString();
23: node.Expanded = true;
24: Tree1.Nodes.Add(node);
25:
26: ResolveSubTree(row, node);
27: }
28: }
29: }
30:
31: private void ResolveSubTree(DataRow dataRow, TreeNode treeNode)
32: {
33: DataRow[] rows = dataRow.GetChildRows("TreeRelation");
34: if (rows.Length > 0)
35: {
36: treeNode.Expanded = true;
37: foreach (DataRow row in rows)
38: {
39: TreeNode node = new TreeNode();
40: node.Text = row["Text"].ToString();
41: treeNode.Nodes.Add(node);
42:
43: ResolveSubTree(row, node);
44: }
45: }
46: }
這段代碼有點復雜,我們逐步來分析:
- 通過CreateDataTable函數拿到需要的數據源;
- 創建一個DataSet數據集,並把剛拿到的數據表加入此數據集,通過還定義了數據之間的聯系(ds.Relations.Add);
- 遍歷數據表中的每一行,找到沒有定義ParentId的行,也即是樹的根節點;
- 將這些根節點添加到樹控件中(Tree1.Nodes.Add);
- 遞歸這些根節點,並通過數據集中數據之間的關系,找到這些根節點的所有子節點,並添加到樹中。
小結
本章我們講解了如何將各種數據源綁定到樹控件,特別是將表格數據綁定到樹控件的做法非常耐人尋味,不過實際項目中最常用的還是將XML文件綁定到樹控件。
下一篇文章我們會講解手風琴控件,並將使用手風琴控件和樹控件組合來創建站點的菜單導航目錄。