【问题标题】:How to fill treeview and nodes according to parent in C#如何在 C# 中根据父级填充树视图和节点
【发布时间】:2023-03-12 14:26:01
【问题描述】:

我在 sql 中有一个表:表数据如下:

catid parentid catname
----- -------- -------------------
1     0        Operating Systems
2     1        Windows
3     1        Linux
4     5        Windows Server 2008 
5     2        Windows Server
6     1        Unix 

父 ID 保留其父 ID。例如; Windows Server 2008 首先出现并且属于 Windows Server(其父级有时会在后面出现)。

在C# 方面,我在数据集中获得了该表,但无法解决其余问题。

for (int i = 0; i < ds2.Tables[0].Rows.Count; i++)
{
    TreeNode root = new TreeNode();
    TreeNode child = new TreeNode();
    if (ds.Tables[0].Rows[i]["parentid"] == 0)
    {

        root.Text = ds.Tables[0].Rows[i]["catname"];
        trview.Nodes.Add(root);
    }
    else
    {
        child.Text = ds.Tables[0].Rows[i]["catname"];
        root.ChildNodes.Add(child);                       
    }                             
}

如何根据表格填写Treeview。我无法解决如何为其设计循环。如果 parentid 属于一个 catid,它将是它的节点。

感谢您的任何建议或帮助

亲切的问候

【问题讨论】:

  • 你有“两个”什么?您指的是“树”吗?
  • 试过编译你的代码吗?它不会在第一行。 Treeview = new treeview();。 Treeview 实例没有变量名,C# 区分大小写;所以你不能实例化一个 Treeview 键入 treeview
  • 对不起,我修正了错误的代码。
  • @josefh75 是 ds2 和 ds DataSet 的不同实例?

标签: c# sql


【解决方案1】:

迭代可能无法解决您的问题。您可以使用迭代添加所有根级节点,然后递归为每个父节点添加子节点。您可以尝试以下方法:

private void BindTreeview()
{
    DataRow[] parentRows = mDataSet.Tables[0].Select("parentid = " + ROOT_PARENT_ID.ToString()); // # Get all root nodes

    foreach (DataRow row in parentRows) // # Add all root nodes to treeview and call for child nodes
    {
        TreeNode node = new TreeNode();
        node.Text = row["catname"].ToString();
        tvCategories.Nodes.Add(node);
        AddChildNodes((int)row["catid"], node);
    }
}

private void AddChildNodes(int catId, TreeNode node) // # Recursive method to add child nodes and call for child nodes of each child node
{
    DataRow[] childRows = mDataSet.Tables[0].Select("parentid = " + catId.ToString()); // # Get all child nodes of given node

    if (childRows.Length == 0) { return; } // # Recursion base case; if given node has no child nodes no more action is taken

    foreach (DataRow row in childRows)
    {
        TreeNode childNode = new TreeNode();
        childNode.Text = row["catname"].ToString();
        node.Nodes.Add(childNode);
        AddChildNodes((int)row["catid"], childNode);
    }
}

它的作用:简单地说;找到根级类别并一一添加到TreeView,调用AddChildNodes方法添加节点和对应的catid,以便添加子节点。 AddChildNodes 方法找到给定 catid 的 1 级以下 子节点,并继续对每个找到的子节点进行递归调用,直到给定节点不再有子节点

这种方法适用于您的情况,我刚刚对其进行了测试。只要记住更换:

  • mDataSet - 使用您的 DataSet 实例
  • tvCategories - 使用您的 TreeView 实例

【讨论】:

  • 谢谢你的例子和想法。据我了解,我需要使用递归函数。如果 root 有 5 个元素,并且子类别的 400 行随机发送给父母。在这种情况下,递归会严重影响页面加载时间吗?我应该改为在 asp.net 模板端手动创建树视图吗?
  • @josefh75 好吧,递归总是比迭代慢。如果您尝试了我和 BartoszKP 建议的两种解决方案,您可以使用不同的虚拟数据负载分析它们,看看是否需要考虑任何效率问题。但是由于您只查询所有数据 一次 并在内存上处理它,我认为性能不会很差
【解决方案2】:

你可以试试这个两遍算法。在这里使用 Tag 属性并不是最干净的方式,但这应该让您了解如何处理此类任务:

var id2node = new Dictionary<int, TreeNode>();

for (int i = 0; i < ds2.Tables[0].Rows.Count; i++)
{
    var node = new TreeNode();
    node.Text = ds.Tables[0].Rows[i]["catname"];
    node.Tag = ds.Tables[0].Rows[i]["parentid"];

    id2node.Add(ds.Tables[0].Rows[i]["catid"], node);
}

foreach (var node in id2node.Values)
{
    TreeNode parent = null;
    if (id2node.TryGetValue((int)node.Tag, out parent))
    {
        parent.ChildNodes.Add(node);
    }
    else
    {
        trview.Nodes.Add(node);
    }
}

【讨论】:

    【解决方案3】:

    您可能会在代码项目中看到这篇文章: Parent-Child-Hierarchical-Relational-Treeview

    编辑:

    也检查一下:how-to-dynamically-populate-treeview-c

    【讨论】:

      猜你喜欢
      • 2016-08-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-30
      • 2014-08-13
      • 2012-06-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多