[原创]FineUI秘密花园(二十四) — 树控件之数据绑定

上一篇文章我们介绍了树控件的基本用法,不过都是通过标签来声明树控件的结构,本章我们会详细讲解如何在后台绑定树控件。

 

绑定到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:  }

这段代码的逻辑很简单:

  1. 获得需要读取XML文件的服务器路径;
  2. 使用StreamReader来读取文件的内容;
  3. 创建XmlDocument实例,并加载XML文件内容;
  4. 设置树控件的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>

image

 

绑定到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:  }

 

image

注意:在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:

image

 

绑定到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:  }

毫无疑问,这段代码生成的层次结构如下所示:

image

当然,这也是我们最终要实现的效果,来看下树控件的初始化代码:

   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:  }

这段代码有点复杂,我们逐步来分析:

  1. 通过CreateDataTable函数拿到需要的数据源;
  2. 创建一个DataSet数据集,并把刚拿到的数据表加入此数据集,通过还定义了数据之间的联系(ds.Relations.Add);
  3. 遍历数据表中的每一行,找到没有定义ParentId的行,也即是树的根节点;
  4. 将这些根节点添加到树控件中(Tree1.Nodes.Add);
  5. 递归这些根节点,并通过数据集中数据之间的关系,找到这些根节点的所有子节点,并添加到树中。

 

小结

本章我们讲解了如何将各种数据源绑定到树控件,特别是将表格数据绑定到树控件的做法非常耐人寻味,不过实际项目中最常用的还是将XML文件绑定到树控件。

下一篇文章我们会讲解手风琴控件,并将使用手风琴控件和树控件组合来创建站点的菜单导航目录。

 

注:《FineUI秘密花园》系列文章由三生石上原创,博客园首发,转载请注明出处。文章目录 官方论坛

posted @ 2012-11-22 09:05 三生石上(FineUI控件) 阅读(...) 评论(...) 编辑 收藏