c# - 如何动态解析数据列表并在树视图中显示结果
问题描述
我有一个具有属性的对象列表。对象类如下所示:
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() 方法,使其接受某种对象,该对象告诉该方法使用多少级别和哪些属性,然后在运行时解析数据并动态创建树视图?是否可以使用递归来做到这一点?
解决方案
好吧,我设法找到了解决方案。它不是递归的,而是动态的。可以在运行时添加或删除属性,下面的代码应该解析它并填充树。
总体思路是遍历所有需要组织的对象,以确定最深层次节点的FullPath。因为我使用属性值作为节点,所以每个对象都已经包含了它的 FullPath 子部分。它们只需要按正确的顺序组合即可。
然后,从手动添加的顶层根节点开始,遍历路径的每一步,检查节点是否存在,是否创建它。此方法成功地在树视图中根据需要呈现我的数据。
FindTreeNodeByFullPath() 方法来自这里。
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;
}
}
}
}
推荐阅读
- sql - 在 SQL 中连接两个查询的结果并在给定条件下生成结果
- python - 将 Python 函数应用于 Pandas 分组的 DataFrame - 加速计算的最有效方法是什么?
- java - 如何部分自动布局图流图
- add-in - 关于 DraftSight / SolidWorks API 的新手提示
- html - 无法单击菜单项_Selenium
- c# - 艾玛迪斯汽车可用性
- python - 如何将烧瓶参数传递给烧瓶函数的装饰器
- nativescript - 如何在 nativescript 中的 NgClass 中应用背景颜色属性?
- javascript - 突出显示单词并发送 GET 请求
- c# - Azure 媒体服务 (v3) Blob 存储、资产和定位器备份