[原创]FineUI秘密花园(二十三) — 树控件概述

树控件用来展示具有层次结构的数据。前面在介绍下拉列表和表格控件时,我们已经接触到模拟树的下拉列表和模拟树的表格,今天我们就来讲解真正的树控件。

 

标签创建的树控件

我们可以直接在ASPX页面中创建树控件,非常直观,比如:

   1:  <ext:Tree ID="Tree1" Width="500px" ShowHeader="true" Title="树控件(内联)" runat="server">
   2:      <Nodes>
   3:          <ext:TreeNode Text="中国" Expanded="true">
   4:              <ext:TreeNode Text="河南省" Expanded="true">
   5:                  <ext:TreeNode Text="驻马店市" NodeID="zhumadian">
   6:                      <ext:TreeNode Text="遂平县" Leaf="false" NodeID="suiping">
   7:                          <ext:TreeNode Text="槐树乡" Leaf="false" NodeID="huaishu">
   8:                              <ext:TreeNode Text="陈庄村" Leaf="true" NodeID="chenzhuang">
   9:                              </ext:TreeNode>
  10:                          </ext:TreeNode>
  11:                      </ext:TreeNode>
  12:                  </ext:TreeNode>
  13:                  <ext:TreeNode Text="漯河市" Leaf="true" NodeID="luohe" />
  14:              </ext:TreeNode>
  15:              // 省略其他节点...
  16:          </ext:TreeNode>
  17:      </Nodes>
  18:  </ext:Tree>

显示效果如下图所示:

image

 

由此可见,一棵树是由TreeNode节点嵌套而来的,下面就来看下TreeNode有哪些属性:

树节点的常用属性

  • Text:树节点文本
  • NodeID:树节点ID
  • Leaf:是否叶子节点
  • Enabled:是否可用
  • Expanded:是否展开
  • NavigateUrl:链接地址
  • Target:链接目标
  • Icon:预定义图标
  • IconUrl:图标地址
  • ToolTip:提示文本
  • SingleClickExpand:单击可切换节点的折叠展开状态

由此可见,树节点可以禁用、可以渲染为超链接、可以定义图标、可以设置提示文本。

 

可以回发的树节点

  • EnablePostBack:是否可以回发(单击树节点)
  • OnClientClick:点击按钮时需要执行的客户端脚本
  • CommandName:命令名称
  • CommandArgument:命令参数

可见,树节点也可以作为一个按钮来触发后台事件,只不过这个事件定义是在树控件上。而CommandName和CommandArgument则类似于表格控件中LinkButtonField定义的同名属性。

 

带复选框的树节点

  • Checked:是否选中
  • EnableCheckBox:是否启用复选框
  • AutoPostBack:是否自动回发(改变复选框状态)

可见,树节点也可以作为一个复选框来触发后台事件。这里AutoPostBack属性就类似于表格控件中CheckBoxField定义的同名属性。

 

可以回发的树节点

通过一个简单示例来讲解其用法:

   1:  <ext:Tree ID="Tree1" Width="500px" OnNodeCommand="Tree1_NodeCommand" ShowHeader="true"
   2:      Title="树控件" runat="server">
   3:      <Nodes>
   4:          <ext:TreeNode Text="中国" Expanded="true">
   5:              <ext:TreeNode Text="河南省" Expanded="true">
   6:                  <ext:TreeNode Text="驻马店市(点击回发)" EnablePostBack="true" Expanded="true" NodeID="Zhumadian">
   7:                      <ext:TreeNode Text="遂平县(点击回发)" EnablePostBack="true" NodeID="Suiping">
   8:                      </ext:TreeNode>
   9:                      <ext:TreeNode Text="西平县(点击回发)" EnablePostBack="true" NodeID="Xiping">
  10:                      </ext:TreeNode>
  11:                  </ext:TreeNode>
  12:                  <ext:TreeNode Text="漯河市" Enabled="true" NodeID="Luohe" />
  13:              </ext:TreeNode>
  14:              // 省略其他节点...
  15:          </ext:TreeNode>
  16:      </Nodes>
  17:  </ext:Tree>

这里有几个关键点:

  1. 为树控件注册节点命令处理函数;
  2. 在需要点击回发的树节点上启用EnablePostBack;
  3. 还可以指定CommandName或者CommandArgument(本例中未用到)。

 

来看下后台处理函数:

   1:  protected void Tree1_NodeCommand(object sender, FineUI.TreeCommandEventArgs e)
   2:  {
   3:      labResult.Text = "你点击了树节点:" + e.Node.Text;
   4:  }

 

运行截图:

image

 

带复选框的树节点

带复选框的树节点只需要启用EnableCheckBox即可,下面的例子我们会更进一步,使用自动回发的复选框树节点来全选/反选所有的子节点,运行效果如下图所示:

image

当选中河南省前面的复选框时,会回发页面并选中河南省下面所有子节点的复选框,这是怎么做到的呢?

 

先看一下页面标签:

   1:   <ext:Tree ID="Tree1" OnNodeCheck="Tree1_NodeCheck" Width="500px" ShowHeader="true"
   2:      Title="树控件" runat="server">
   3:      <Nodes>
   4:          <ext:TreeNode Text="中国" EnableCheckBox="true" AutoPostBack="true" Expanded="true">
   5:              <ext:TreeNode AutoPostBack="true" Text="河南省" EnableCheckBox="true" Expanded="true">
   6:                  <ext:TreeNode Text="驻马店市" AutoPostBack="true" EnableCheckBox="true" NodeID="zhumadian">
   7:                      <ext:TreeNode Text="遂平县" AutoPostBack="true" EnableCheckBox="true" NodeID="Suiping">
   8:                      </ext:TreeNode>
   9:                      <ext:TreeNode Text="西平县" AutoPostBack="true" EnableCheckBox="true" NodeID="Xiping">
  10:                      </ext:TreeNode>
  11:                  </ext:TreeNode>
  12:                  <ext:TreeNode Text="漯河市" AutoPostBack="true" EnableCheckBox="true" NodeID="luohe" />
  13:              </ext:TreeNode>
  14:              // 省略其他节点...
  15:          </ext:TreeNode>
  16:      </Nodes>
  17:  </ext:Tree>

这里有几个关键点:

  1. 为树控件注册节点选中处理函数;
  2. 在需要显示复选框的节点上启用EnableCheckBox;
  3. 在需要自动回发复选框的树节点上启用AutoPostBack;

 

再来看下选中节点复选框的处理函数:

   1:  protected void Tree1_NodeCheck(object sender, FineUI.TreeCheckEventArgs e)
   2:  {
   3:      if (e.Checked)
   4:      {
   5:          Tree1.CheckAllNodes(e.Node.Nodes);
   6:      }
   7:      else
   8:      {
   9:          Tree1.UncheckAllNodes(e.Node.Nodes);
  10:      }
  11:  }

这里调用了CheckAllNodes函数来选中所有的子节点,当然我们也可以手工递归所有的子节点来完成此操作。

下面是使用递归的方式来完成此操作的参考代码:

   1:  protected void Tree1_NodeCheck(object sender, FineUI.TreeCheckEventArgs e)
   2:  {
   3:        if (!e.Node.Leaf)
   4:        {
   5:            CheckTreeNode(e.Node.Nodes, e.Checked);
   6:        }
   7:  }
   8:   
   9:  private void CheckTreeNode(TreeNodeCollection nodes, bool isChecked)
  10:  {
  11:      foreach (TreeNode node in nodes)
  12:      {
  13:          node.Checked = isChecked;
  14:          if (!node.Leaf)
  15:          {
  16:              CheckTreeNode(node.Nodes, isChecked);
  17:          }
  18:      }
  19:  } 

 

延迟加载的树节点

在上面这些例子中,不知道你有没有发现一个细节,有时我们为子节点设置了Leaf=true,有时又没有设置,不过似乎都能正常运行,这是怎么回事?

其实,是否为树节点设置Leaf属性都可以,因为FineUI内部会重新递归所有的子节点,将拥有子节点的节点Leaf属性设为false,反之设为true。控制这一行为的属性就是AutoLeafIdentification(默认值为true)。

 

如果将树控件的AutoLeafIdentification设为false,则我们就需要为每一个子节点设置Leaf=true(默认为false),如果没有为一个理应成为子节点的节点设置Leaf=true,则此节点就会被渲染为一个可折叠展开的父节点,展开此节点时就会触发树控件的NodeExpand事件。

 

正好,我们可以利用这一特性来完成延迟加载的树节点,是不是很巧妙。下面通过一个示例来演示。

先看页面的标签:

   1:  <ext:Tree ID="Tree1" EnableArrows="true" OnNodeExpand="Tree1_NodeExpand" Width="500px"
   2:      ShowHeader="true" Title="延迟加载的树控件" AutoLeafIdentification="false" runat="server">
   3:      <Nodes>
   4:          <ext:TreeNode Text="中国" Expanded="true">
   5:              <ext:TreeNode Text="河南省" Expanded="true">
   6:                  <ext:TreeNode Text="驻马店市(此节点延迟加载)" NodeID="zhumadian">
   7:                  </ext:TreeNode>
   8:                  <ext:TreeNode Text="漯河" NodeID="luohe" Leaf="true" />
   9:              </ext:TreeNode>
  10:              // 省略其他节点...
  11:          </ext:TreeNode>
  12:      </Nodes>
  13:  </ext:Tree>

这里有几个关键点:

  1. 为树控件注册节点展开处理函数;
  2. 为树控件设置AutoLeafIdentification=false;
  3. 为真正的子节点设置Leaf=true;
  4. 需要延迟加载的树节点不要设置Leaf属性(即默认为false)。

 

先来看下页面第一次打开的截图:

image

此时“驻马店市”下面并没有子节点,因此展开此节点时会触发树控件的节点展开事件。

 

下面来看下节点展开事件的处理函数:

   1:  protected void Tree1_NodeExpand(object sender, FineUI.TreeExpandEventArgs e)
   2:  {
   3:      DynamicAppendNode(e.Node);
   4:  }
   5:   
   6:  private void DynamicAppendNode(TreeNode parentNode)
   7:  {
   8:      parentNode.Expanded = true;
   9:   
  10:      TreeNode node = null;
  11:      switch (parentNode.NodeID)
  12:      {
  13:          case "zhumadian":
  14:              node = new TreeNode();
  15:              node.Text = "遂平县";
  16:              node.Leaf = false;
  17:              node.NodeID = "suiping";
  18:              parentNode.Nodes.Add(node);
  19:   
  20:              node = new TreeNode();
  21:              node.Text = "西平县";
  22:              node.Leaf = true;
  23:              node.NodeID = "xiping";
  24:              parentNode.Nodes.Add(node);
  25:              break;
  26:          case "suiping":
  27:              node = new TreeNode();
  28:              node.Text = "槐树乡";
  29:              node.Leaf = false;
  30:              node.NodeID = "huaishu";
  31:              parentNode.Nodes.Add(node);
  32:              break;
  33:          case "huaishu":
  34:              node = new TreeNode();
  35:              node.Text = "陈庄村";
  36:              node.Leaf = true;
  37:              node.NodeID = "chenzhuang";
  38:              parentNode.Nodes.Add(node);
  39:              break;
  40:      }
  41:  }

这段代码不仅处理展开“驻马店市”的情况,而且处理下面的层次结构,通过NodeID进行关联,大家可以认真分析下这段代码。

 

下面是运行截图:

image

 

注:第一次展开“驻马店市”之后,就向其中添加了子节点,所以折叠后再次展开此节点就不会触发节点展开事件了。

 

小结

本章我们介绍了树控件的各种用法,树节点不仅可以被渲染为普通文本、超链接、可回发的文本,而且可以渲染为带自动回发复选框的文本,同时我们还讲解了延迟树节点的用法。

下一篇文章我们会介绍如何将各种不同的数据源绑定到将树控件。

 

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

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