我得到了这个课程:
public class hierarchymain
{
public String label; // Label to be displayed in treeview
public int parentId; // ID of the parent. Root have 0 in parent ID
public int ID; //Id in table. ignore it
}
但我无法找到将其加载到树视图中的正确方法......
hierarchy = new List<Hierarchymain> {
new Hierarchymain{Label="ONE",ParentID=0, ID=0},
new Hierarchymain{Label="TWO", ParentID=0, ID=1},
new Hierarchymain{Label="THREE", ParentID=1, ID=2},
new Hierarchymain{Label="Four", ParentID=2, ID=3},
new Hierarchymain{Label="five", ParentID=3, ID=4},
new Hierarchymain{Label="six", ParentID=4, ID=5},
new Hierarchymain{Label="seven", ParentID=0, ID=6}
};
任何想法?
答案 0 :(得分:2)
填充树时,您可以使用字典检索要添加的新项目的父项。如果我们可以假设父母总是在孩子面前定义,那么第二个foreach
可以省略。
var dict = new Dictionary<int, TreeNode>();
var orphans = new Queue<Hierarchymain>();
foreach (Hierarchymain item in hierarchy)
{
TreeNode newNode = new TreeNode(item.Label);
TreeNode parent;
if (dict.TryGetValue(item.ParentID, out parent))
parent.Nodes.Add(newNode);
else if (item.ParentID == 0)
treeView1.Nodes.Add(newNode);
else
orphans.Enqueue(item);
dict.Add(item.ID, newNode);
}
// processing nodes, whose parents were created later
foreach (Hierarchymain item in orphans)
{
TreeNode orphan = dict[item.ID];
TreeNode parent;
if (dict.TryGetValue(item.ParentID, out parent))
parent.Nodes.Add(orphan); // parent found
else
treeView1.Nodes.Add(orphan); // the node is a real orphan, adding to the root
}
答案 1 :(得分:1)
有很多方法可以做到这一点。在我开始之前,我想指出,正如许多评论者提到的那样,提供的示例不正确 - 如果ParentID=0
表示根节点,那么您不应该有ID=0
的节点,所以我&# 39;将使用与您相同的数据,但每个项目ID都会增加。以下是我将用于测试的更正(并且另外改组)的数据:
var source = new List<Hierarchymain> {
new Hierarchymain{ Label="THREE", ParentID=2, ID=3},
new Hierarchymain{ Label="six", ParentID=5, ID=6},
new Hierarchymain{ Label="Four", ParentID=3, ID=4},
new Hierarchymain{ Label="five", ParentID=4, ID=5},
new Hierarchymain{ Label="TWO", ParentID=1, ID=2},
new Hierarchymain{ Label="seven", ParentID=0, ID=7},
new Hierarchymain{ Label="ONE", ParentID=0, ID=1},
};
现在的解决方案。
(A)简单的递归实现:从根项开始,为每个项创建一个节点,然后对其子项执行相同的操作。
static void PopulateA(TreeView treeView, IEnumerable<Hierarchymain> source)
{
AddNodes(treeView.Nodes, 0, source);
}
static void AddNodes(TreeNodeCollection parentNodes, int parentID, IEnumerable<Hierarchymain> source)
{
foreach (var item in source.Where(item => item.ParentID == parentID))
{
var node = parentNodes.Add(item.Label);
AddNodes(node.Nodes, item.ID, source);
}
}
(B)(A)的不同实施。 (A)的问题在于它具有O(N ^ 2)时间复杂度。但是,通过在开头准备查找结构并保持简单性,可以很容易地改进这一点。
static void PopulateB(TreeView treeView, IEnumerable<Hierarchymain> source)
{
AddNodes(treeView.Nodes, 0, source.ToLookup(item => item.ParentID));
}
static void AddNodes(TreeNodeCollection parentNodes, int parentID, ILookup<int, Hierarchymain> source)
{
foreach (var item in source[parentID])
{
var node = parentNodes.Add(item.Label);
AddNodes(node.Nodes, item.ID, source);
}
}
(C)上述迭代实现。如果层次结构太深,则递归实现将失败并显示StackOverflowException
。这可以通过将它们变成迭代版本来解决,牺牲了可读性和简单性。这相当于(B):
static void PopulateC(TreeView treeView, IEnumerable<Hierarchymain> source)
{
var itemsByParentId = source.ToLookup(item => item.ParentID);
var parentNodesStack = new Stack<TreeNodeCollection>();
var childEnumeratorStack = new Stack<IEnumerator<Hierarchymain>>();
var parentNodes = treeView.Nodes;
var childEnumerator = itemsByParentId[0].GetEnumerator();
try {
while (true)
{
while (childEnumerator.MoveNext())
{
var item = childEnumerator.Current;
var node = parentNodes.Add(item.Label);
parentNodesStack.Push(parentNodes);
childEnumeratorStack.Push(childEnumerator);
parentNodes = node.Nodes;
childEnumerator = itemsByParentId[item.ID].GetEnumerator();
}
if (childEnumeratorStack.Count == 0) break;
childEnumerator.Dispose();
childEnumerator = childEnumeratorStack.Pop();
parentNodes = parentNodesStack.Pop();
}
}
finally
{
childEnumerator.Dispose();
while (childEnumeratorStack.Count != 0) childEnumeratorStack.Pop().Dispose();
}
}
(D)这是我经常使用的算法。同样的想法可以递归地实现,但我使用它是出于与(C)中提到的相同的原因。它的工作原理如下:在处理过程中,我们按ID维护已创建节点的映射,以便能够定位父节点。对于输入序列中的每个项目,我们构建一个堆栈,其中包含尚未创建节点的项目,然后以相反的顺序处理它。这样我们就可以确保父母在孩子面前创造。
static void PopulateD(TreeView treeView, IEnumerable<Hierarchymain> source)
{
var itemById = source.ToDictionary(item => item.ID);
var nodeById = new Dictionary<int, TreeNode>();
var addStack = new Stack<Hierarchymain>();
foreach (var nextItem in source)
{
// Collect the info about the nodes that need to be created and where
TreeNodeCollection parentNodes;
for (var item = nextItem; ; item = itemById[item.ParentID])
{
TreeNode node;
if (nodeById.TryGetValue(item.ID, out node))
{
// Already processed
parentNodes = node.Nodes;
break;
}
addStack.Push(item);
if (item.ParentID == 0)
{
// Root item
parentNodes = treeView.Nodes;
break;
}
}
// Create node for each collected item in reverse order
while (addStack.Count > 0)
{
var item = addStack.Pop();
var node = parentNodes.Add(item.Label);
nodeById.Add(item.ID, node);
parentNodes = node.Nodes;
}
}
}
希望有所帮助。