65.9K
CodeProject 正在变化。 阅读更多。
Home

层次数据结构的动态绑定到 Treeview 控件

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.88/5 (20投票s)

2010年12月29日

CPOL

3分钟阅读

viewsIcon

178544

downloadIcon

5730

本文提供了一个代码库,用于使用 ASP.NET Treeview 控件实现动态层级数据结构。

目录

  1. 引言
  2. 业务需求
  3. 解决方案
  4. 数据库实现
  5. 递归函数
  6. 结论
  7. 参考

引言

ASP.NET Treeview 控件是用于表示树视图层级数据结构的最常用的服务器控件。 大多数时候,我们都会遇到与数据的层级树结构表示相关的需求; 如果叶节点的深度非常大,这会变得更加复杂。 在这种情况下,我们可能需要寻找通用解决方案。 本文将帮助开发人员使用以下逻辑或实现来解决类似情况。

业务需求

例如,我们有一个业务问题,需要以层级方式表示某个家庭或类别。 在这种情况下,遍历 XML 树或结构化数据库将成为一项挑战。 即使解析也只是问题的一部分,然后以该层级模式的图形视图表示它。

注意: 这里的挑战在于数据结构不是硬编码的,并且任何时候都可以在运行时添加新的叶节点或父节点。 因此,拥有 XML 结构将是一个挑战,因为解析、定位父节点和更新 XML 数据将给程序员带来额外的开销。

FamilyTree.JPG

解决方案

要遵循的方法

  • 以所需的层级格式构造数据 - Datatable 架构。
  • 建立解析逻辑。 编写递归函数
  • 将其绑定到 Tree view 控件。

此处的重要贡献因素是创建良好的数据表结构并将其绑定到树视图控件。

  • ASP.NET TreeView 控件
  • 技术栈
  • ASP.NET
  • SQL Server 2005

数据库实现

创建表 tbl_Tree_Hierarchy

创建存储过程 ssp_get_hierarchy:这将给出 Node_ID 及其子信息以及叶节点或分支所属的级别或深度。 以下是上述存储过程的结果集。 在 SQL Server 2005 中使用公共表表达式来使用 WITH 子句引用递归数据集是最好的。

递归函数

创建递归函数以遍历层级树数据结构。 此功能是使用 ASP.NET 2.0 开发的,并且可以使用 CSharp .NET 3.5 使用 LINQ 来避免递归函数。 使用匿名委托,我们可以将集合对象与某些逻辑条件进行比较。 一旦过滤了结果集,就可以遍历它并将其作为对象项添加到树视图控件。

创建包含 Htree 对象的 HierarchyTrees 泛型集合。

public class HierarchyTrees : List <HierarchyTrees.HTree>
{ 
    public class HTree 
    {            
        private string m_NodeDescription;
        private int m_UnderParent;
        private int m_LevelDepth;
        private int m_NodeID;
        
        public int NodeID 
        { get {return m_NodeID;}
            set { m_NodeID=value; }
        } 
        
        public string NodeDescription
        {
            get { return m_NodeDescription; }
            set { m_NodeDescription = value; }
        }
        public int UnderParent
        {
            get { return m_UnderParent; }
            set { m_UnderParent = value; }
        }
        public int LevelDepth
        {
            get { return m_LevelDepth; }
            set { m_LevelDepth = value; }
        }
    } 
}  

PopulateTreeview() 函数将从数据库中获取 recordset 并填充泛型集合树。

private void PopulateTreeview() {    
     this.tvHierarchyView.Nodes.Clear();     
     HierarchyTrees hierarchyTrees = new HierarchyTrees();    
     HierarchyTrees.HTree objHTree=null;
     using (SqlConnection connection = new SqlConnection
     (@"Persist Security Info=False;Integrated Security=SSPI;
     database=FamilyTree;server=[Local]"))             
     {         
         connection.Open();
         using (SqlCommand command = 
         new SqlCommand("SSP_GET_HIERARCHY", connection))     
         {             command.CommandType = System.Data.CommandType.StoredProcedure;
             SqlDataReader reader = command.ExecuteReader
             (System.Data.CommandBehavior.CloseConnection);
             while (reader.Read())             
             {              
                 objHTree=new HierarchyTrees.HTree();      
                                 
             objHTree.LevelDepth = int.Parse(reader["LEVEL_DEPTH"].ToString());
             objHTree.NodeID = int.Parse(reader["NODE_ID"].ToString());
             objHTree.UnderParent = int.Parse(reader["UNDER_PARENT"].ToString());
             objHTree.NodeDescription = reader["NODE_DESCRIPTION"].ToString();
             hierarchyTrees.Add(objHTree);
             }         
         }     
     }       
     //Iterate through Collections.
     foreach (HierarchyTrees.HTree hTree in hierarchyTrees)     
     {
         //Filter the collection HierarchyTrees based on 
         //Iteration as per object Htree Parent ID 
         HierarchyTrees.HTree parentNode = hierarchyTrees.Find
         (delegate(HierarchyTrees.HTree emp) 
		{ return emp.NodeID == hTree.UnderParent; });
         //If parent node has child then populate the leaf node.
         if (parentNode != null)
         {         
             foreach (TreeNode tn in tvHierarchyView.Nodes)
             {
                 //If single child then match Node ID with Parent ID
                 if (tn.Value == parentNode.NodeID.ToString())
                 {
                     tn.ChildNodes.Add(new TreeNode
                     (hTree.NodeDescription.ToString(), hTree.NodeID.ToString()));
                 }
                 
                 //If Node has multiple child ,
                 //recursively traverse through end child or leaf node.
                 if (tn.ChildNodes.Count > 0)
                 {                    
                     foreach (TreeNode ctn in tn.ChildNodes)
                     {
                         RecursiveChild(ctn, parentNode.NodeID.ToString(), hTree);
                     }
                 }
             }                
         }
         //Else add all Node at first level 
         else
         {               
             tvHierarchyView.Nodes.Add(new TreeNode
             (hTree.NodeDescription, hTree.NodeID.ToString()));
         } 
         }     
     tvHierarchyView.ExpandAll(); 
}

创建递归函数以遍历层级树数据结构。 此功能是使用 ASP.NET 2.0 开发的,并且可以使用 CSharp .NET 3.5 使用 LINQ 来避免递归函数。 使用匿名委托,我们可以将集合对象与某些逻辑条件进行比较。 一旦过滤了结果集,就可以遍历它并将其作为对象项添加到树视图控件。 创建包含 Htree 对象的 HierarchyTrees 泛型集合。

public void RecursiveChild
(TreeNode tn, string searchValue, HierarchyTrees.HTree hTree)
{
    if (tn.Value == searchValue)
    {
        tn.ChildNodes.Add(new TreeNode
        (hTree.NodeDescription.ToString(), hTree.NodeID.ToString()));
    }
    if (tn.ChildNodes.Count > 0)
    {
        foreach (TreeNode ctn in tn.ChildNodes)
        {
            RecursiveChild(ctn, searchValue,hTree);
        }
    }
} 

结论

欢迎任何想法、更正和建议。

参考文献

以下参考适用于 Winform treeview 控件,我编写了上面的文章是为了使其也适用于 ASP.NET treeview 控件。 winform 和 ASP.NET treeview 控件之间的重要区别在于 FindNode

在 winform treeview 控件中,我们有 tvHierarchyView.Nodes.Find,它查找给定的节点条件并帮助我们在给定的节点值处添加 Htree 对象项,因此可以使用 LINQ 并摆脱递归函数。

与 Winform 不同,ASP.NET treeview 控件公开了 tvHierarchyView.FindNode(XML Address path),它更适用于 XML 数据类型,因此没有太大帮助。

© . All rights reserved.