【问题标题】:How to parse list of data dynamically and show the result in treeview如何动态解析数据列表并在树视图中显示结果
【发布时间】:2021-02-21 20:12:27
【问题描述】:

我有一个带有属性的对象列表。对象类如下图:

public class ElementImpression
{
    public int ElementId { get; private set; }
    public string FamilyAndTypeName { get; private set; }
    public string CategoryName { get; private set; }
    public int CategoryNumber { get; private set; }
    public string SystemAbbreviation { get; private set; }
    public ElementImpression(Element e)
    {
        ElementId = e.Id.IntegerValue;
        FamilyAndTypeName = e.get_Parameter(BuiltInParameter.ELEM_FAMILY_AND_TYPE_PARAM).AsValueString();
        CategoryName = e.Category.Name;
        CategoryNumber = e.Category.Id.IntegerValue;
        SystemAbbreviation = e.get_Parameter(BuiltInParameter.RBS_DUCT_PIPE_SYSTEM_ABBREVIATION_PARAM).AsString();
    }
}

目标是解析列表并在 TreeView 控件中创建结构化的分层表示。层次结构中的级别数以及用作节点的属性由用户在运行时定义。 我已成功创建以下树视图: Treeview 使用以下代码:

private void UpdateTreeView(object sender, MyEventArgs e)
    {
        //Level 0: All
        //Level 1: System Abbreviation
        //Level 2: Category Name
        //Level 3: Family and Type Name

        treeView1.BeginUpdate();
        treeView1.Nodes.Clear();
        
        //Payload is a container object holding the list to be parsed. It is cached as a property in the form.
        //Payload.ElementsInSelection is the list of objects to parse.
        var lv1Group = Payload.ElementsInSelection.GroupBy(x => x.SystemAbbreviation);
        treeView1.Nodes.Add("All");

        int i = -1;
        foreach (IGrouping<string, ElementImpression> group1 in lv1Group)
        {
            treeView1.Nodes[0].Nodes.Add(group1.Key);

            var lv2Group = group1.ToList().GroupBy(x => x.CategoryName);

            i++;
            int j = -1;
            foreach (IGrouping<string,ElementImpression> group2 in lv2Group)
            {
                treeView1.Nodes[0].Nodes[i].Nodes.Add(group2.Key);

                var lv3Group = group2.ToList();

                j++;
                int k = -1;
                foreach (ElementImpression ei in lv3Group)
                {
                    k++;
                    treeView1.Nodes[0].Nodes[i].Nodes[j].Nodes.Add(ei.FamilyAndTypeName);

                    treeView1.Nodes[0].Nodes[i].Nodes[j].Nodes[k].Nodes.Add(ei.ElementId.ToString());
                    treeView1.Nodes[0].Nodes[i].Nodes[j].Nodes[k].Nodes.Add(ei.CategoryNumber.ToString());
                }
            }
        }
        treeView1.EndUpdate();
    }

是否可以重写 UpdateTreeView() 方法,使其接受某种对象,该对象告诉该方法使用多少级别和使用哪些属性,然后在运行时解析数据并动态创建树视图?是否可以使用递归来做到这一点?

【问题讨论】:

  • 这是一个相当广泛的问题,但是是的,两者都是可能的。请显示您尝试过的代码,以便我们查看有什么问题,并将问题缩小到您遇到的具体问题。
  • 嗨。感谢您花时间回答。好吧,我不能再进步了,问题最后一部分显示的代码是我能得到的。

标签: c# recursion dynamic treeview


【解决方案1】:

好吧,我设法找到了解决方案。它不是递归的,而是动态的。可以在运行时添加或删除属性,下面的代码应该解析它并填充树。

总体思路是遍历所有需要组织的对象,确定最深层次节点的FullPath。因为我使用属性值作为节点,所以每个对象都已经包含了它的 FullPath 子部分。它们只需要按正确的顺序组合即可。

然后,从顶层的根节点开始,手动添加,遍历路径的每一步,检查节点是否存在,如果不创建它。此方法成功地在树视图中根据需要呈现我的数据。

FindTreeNodeByFullPath() 方法来自here

public void PopulateTreeview()
    {
        //Manually add root node
        treeView1.Nodes.Add("All");
        
        //Loop all the objects
        foreach (ElementImpression e in Elements)
        {
            //Declare array to hold the names of all nodes in path to the element
            //PropertiesList is an object containing information about what properties to consider and how many.
            string[] pathParts = new string[PropertiesList.Length + 2];

            //The name of root node
            pathParts[0] = "All";

            //Populate the path parts with values from elements
            for (int i = 0; i < PropertiesList.Length; i++)
            {
                pathParts[i + 1] = PropertiesList[i].getPropertyValue(e);
            }
            //Finish the list with the name of the element (id currently)
            pathParts[pathParts.Length - 1] = e.Id.IntegerValue.ToString();

            //Create an array of all full paths from root node to the element
            string[] fullPaths = new string[PropertiesList.Length + 2];
            for (int i = 0; i < fullPaths.Length; i++)
            {
                if (i == 0) fullPaths[i] = pathParts[i];
                else fullPaths[i] = fullPaths[i - 1] + "." + pathParts[i];
            }

            //Iterate through the fullPaths to determine, if node exists, if not -> create it
            TreeNode previousNode = null;
            for (int i = 0; i < fullPaths.Length; i++)
            {
                TreeNode foundNode = treeView1.Nodes.FindTreeNodeByFullPath(fullPaths[i]);
                if (foundNode == null)
                {
                    if (previousNode != null) previousNode = previousNode.Nodes.Add(pathParts[i]);
                }
                else
                {
                    previousNode = foundNode;
                    continue;
                }
            }
        }
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-02
    • 2016-06-15
    相关资源
    最近更新 更多