从Tree <t>对象</t>填充TreeView

时间:2014-12-11 05:16:54

标签: c#

我需要在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()));
                }
            }
        }
    }
}

4 个答案:

答案 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结构子集的三种方法:

  1. 过滤:从旧结构创建新的DataTreeNode结构,不包括包含不需要的叶节点的子树。加载结果。
  2. 向DataTreeNode添加一个属性,该属性表示其子树的叶节点中的值范围,如Huffman树。然后在加载时,在添加给定的DataTreeNode之前检查属性。
  3. 对于每个DataTreeNode创建一个TreeNode,但如果TreeNode的子树的叶子节点与所需的值不匹配,则丢弃它。
  4. 下面是选项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;
    }