zoukankan      html  css  js  c++  java
  • [原创]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秘密花园》系列文章由三生石上原创,博客园首发,转载请注明出处。文章目录 官方论坛

  • 相关阅读:
    简爱 灵魂所在
    charles抓取http/https
    Class.forName()用法
    ArrayList源码剖析
    java中的多线程
    分布式负载均衡缓冲系统,如何快速定位到是那个服务器
    maven依赖jar包时版本冲突的解决
    简单工厂模式设计(java反射机制改进)
    Fiddler 抓包工具使用详解
    Fiddler 使用
  • 原文地址:https://www.cnblogs.com/sanshi/p/2781941.html
Copyright © 2011-2022 走看看