我需要在Tree<T>
中显示TreeView
层次结构,区分树节点和树叶。
Tree对象是在运行时构造的,并且不知道它的深度。不是二叉树。 这是DataTree类:
public class TreeNode<T> : IEnumerable<TreeNode<T>>
{
public T Data { get; set; }
public TreeNode<T> Parent {get; set;}
public ICollection<TreeNode<T>> Children {get; set;}
.....
.....
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public IEnumerator<TreeNode<T>> GetEnumerator()
{
yield return this;
foreach (var directChild in this.Children)
{
foreach (var anyChild in directChild)
yield return anyChild;
}
}
}
这是填充TreeView的代码:
public void CreateTreeView()
{
AttributesTreeView=new TreeView();
foreach(TreeNode<string> entry in NewAttTree)
{
if(entry.Children.Count>0)
{
int tn=AttributesTreeView.Nodes.Add(new TreeNode(entry.Data.ToString().Replace("|",string.Empty)));
foreach(TreeNode<string> str in entry.Children)
{
if(tn!=0)
{
int itn=AttributesTreeView.Nodes[tn].Nodes.Add(new TreeNode(str.Data.ToString()));
}
}
}
}
}
答案 0 :(得分:1)
你在这里做的是拿一棵树,并将那棵树中的每个节点投射到别的东西,同时保持那棵树的结构。这实际上非常简单。只需创建一个查找,将每个节点映射到其所有子节点,然后遍历每个节点,查找自己&#34;然后将查找中的所有子项添加到新节点:
var roots = new TreeNode<string>[] { }; //the original data to map
var lookup = roots.SelectMany(node => node)
.ToLookup(node => node.Parent, node => new
{
node,
UINode = new TreeNode(node.Data),
});
foreach (var pair in lookup.SelectMany(group => group))
foreach (var child in lookup[pair.node])
pair.UINode.Nodes.Add(child.UINode);
TreeView view = new TreeView();
foreach (var root in lookup[null]) //assume nodes with a null parent are roots
view.Nodes.Add(root.UINode);
答案 1 :(得分:0)
好的,明白了。
TreeNode newNode=new TreeNode("SEARCH");
AttributesTreeView.Nodes.Add(newNode);
CreateTreeView(NewAttTree,newNode);
public void CreateTreeView(DataTreeNode<string> root, TreeNode parentNode)
{
foreach(DataTreeNode<string> node in root.Children)
{
try
{
TreeNode newNode=new TreeNode(node.Data.ToString());
parentNode.Nodes.Add(newNode);
CreateTreeView(node,newNode);
}
catch (System.Exception e)
{
}
}
@groverboy:感谢你朝着正确的方向前进。
还有一个问题出现了: 我们如何扫描DataTree结构并仅使用具有特定值[s]叶子的节点填充TreeView。我的意思是在DFT遍历中,我们如何决定在访问叶子之前添加节点并决定是否符合过滤条件?
答案 2 :(得分:0)
我可以想到加载DataTreeNode结构子集的三种方法:
下面是选项3的伪代码,使用HashSet查找所需的叶节点值。
void LoadDataTreeNode(TreeView treeView, DataTreeNode<T> dataTreeNode, HashSet<T> hashSet)
{
treeView.Nodes.Clear();
LoadDataTreeNode(treeView.Nodes, dataTreeNode, hashSet);
}
bool LoadDataTreeNode(TreeNodeCollection treeNodes, DataTreeNode<T> dataTreeNode, HashSet<T> hashSet)
{
bool result = hashSet.Contains(dataTreeNode.Data);
if (result)
{
var treeNode = new TreeNode(dataTreeNode.Data.ToString());
// Use this treeNode if at least one of its subtrees contains
// the required leaf node values. Assume that all other
// subtrees will be discarded by the relevant recursive calls.
result = false;
foreach (var child in dataTreeNode.Children)
{
if (LoadDataTreeNode(treeNode.Nodes, child, hashSet))
{
result = true;
}
}
if (result)
{
treeNodes.Add(treeNode);
}
}
return result;
}
答案 3 :(得分:0)
@groverboy:我尝试了你的方法,但它没有工作,我注意到它不会超过第一个if子句,除非根DataTreeNode适合账单,否则它返回而不迭代数据一棵树。 这是我提出的方法,基于你的代码:它工作,但多次添加相同的分支,我必须是盲目但我不明白为什么;也许是另一双眼睛。
bool PopulateTreeNode(DataTreeNode<string> dataNode,TreeNode treeNodes,string filter,bool ignoreCase)
{
if(dataNode.IsLeaf)
{
if(WcMatchExtensionMethods.WcMatches(dataNode.Data,filter,ignoreCase))
{
treeNodes.Nodes.Add(new TreeNode(dataNode.Data.ToString()));
return true;
}
else
return false;
}
bool result = false;
TreeNode treeNode=new TreeNode(dataNode.Data.ToString());
foreach (DataTreeNode<string> child in dataNode.Children)
{
if(PopulateTreeNode(child,treeNode,filter,ignoreCase))
{
treeNodes.Nodes.Add(treeNode);
result = true;
}
}
return result;
}