C# 从树填充树视图<;T>;对象

C# 从树填充树视图<;T>;对象,c#,C#,我需要在TreeView中显示一个树层次结构,区分树节点和树叶 树对象是在运行时构造的,不知道其深度。不是二叉树。 这是DataTree类: public class TreeNode<T> : IEnumerable<TreeNode<T>> { public T Data { get; set; } public TreeNode<T> Parent {get; set;} public ICollecti

我需要在
TreeView
中显示一个
层次结构,区分树节点和树叶

树对象是在运行时构造的,不知道其深度。不是二叉树。 这是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;
        }
    }
}
公共类树节点:IEnumerable
{
公共T数据{get;set;}
公共树节点父节点{get;set;}
公共ICollection子项{get;set;}
.....
.....
IEnumerator IEnumerable.GetEnumerator()
{
返回GetEnumerator();
}
公共IEnumerator GetEnumerator()
{
收益回报这一点;
foreach(此.Children中的var directChild)
{
foreach(directChild中的var 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()));
                }
            }
        }
    }
}
public void CreateTreeView()
{
AttributesTreeView=newtreeview();
foreach(NewAttTree中的TreeNode条目)
{
如果(条目.Children.Count>0)
{
int tn=AttributesTreeView.Nodes.Add(新树节点(entry.Data.ToString().Replace(“|”,string.Empty));
foreach(entry.Children中的TreeNode str)
{
如果(tn!=0)
{
int itn=AttributesTreeView.Nodes[tn].Nodes.Add(新树节点(str.Data.ToString());
}
}
}
}
}
好的,明白了

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)
        {
        }
    }
treenodenewnode=newtreenode(“搜索”);
AttributeStreamView.Nodes.Add(新节点);
CreateTreeView(NewAttTree,newNode);
public void CreateTreeView(DataTreeNode根、TreeNode父节点)
{
foreach(root.Children中的DataTreeNode节点)
{
尝试
{
TreeNode newNode=新的TreeNode(node.Data.ToString());
parentNode.Nodes.Add(newNode);
CreateTreeView(节点,新节点);
}
捕获(System.e例外)
{
}
}
@格罗弗比:谢谢你朝着正确的方向努力

还有一个问题出现了:
我们如何扫描DataTree结构并仅使用具有特定值叶子的节点填充TreeView。我的意思是,在DFT遍历中,我们如何在访问叶子并确定是否以及哪些符合筛选条件之前决定添加节点?

我可以想出三种方法来加载DataTreeNode结构的子集:

  • 筛选:从旧结构创建新的DataTreeNode结构,不包括包含不需要的叶节点的子树。加载结果
  • 向DataTreeNode添加表示其子树叶节点中值范围的属性,如Huffman树。然后在加载时,在添加给定DataTreeNode之前检查该属性
  • 对于每个DataTreeNode,创建一个TreeNode,但如果其子树的叶节点与所需值不匹配,则丢弃该TreeNode
  • 下面是选项3的伪代码,使用哈希集查找所需的叶节点值

    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;
    }
    
    void LoadDataTreeNode(TreeView TreeView,DataTreeNode DataTreeNode,HashSet HashSet)
    {
    treeView.Nodes.Clear();
    LoadDataTreeNode(treeView.Nodes、dataTreeNode、hashSet);
    }
    bool LoadDataTreeNode(TreeNodeCollection treeNodes、DataTreeNode DataTreeNode、HashSet HashSet)
    {
    bool result=hashSet.Contains(dataTreeNode.Data);
    如果(结果)
    {
    var treeNode=new treeNode(dataTreeNode.Data.ToString());
    //如果至少有一个子树包含
    //所需的叶节点值。假定所有其他
    //相关递归调用将丢弃子树。
    结果=假;
    foreach(dataTreeNode.Children中的变量child)
    {
    if(LoadDataTreeNode(treeNode.Nodes、子节点、hashSet))
    {
    结果=真;
    }
    }
    如果(结果)
    {
    添加(treeNode);
    }
    }
    返回结果;
    }
    
    @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;
        }
    
    bool PopulateTreeNode(datatreenodedatanode,treenodetreenodes,字符串过滤器,bool ignoreCase)
    {
    if(dataNode.IsLeaf)
    {
    if(WcMatchExtensionMethods.WcMatches(dataNode.Data,filter,ignoreCase))
    {
    添加(新的TreeNode(dataNode.Data.ToString());
    返回true;
    }
    其他的
    返回false;
    }
    布尔结果=假;
    TreeNode TreeNode=新的TreeNode(dataNode.Data.ToString());
    foreach(dataNode.Children中的DataTreeNode子节点)
    {
    if(PopulateTreeNode(子节点、树节点、过滤器、ignoreCase))
    {
    treeNodes.Nodes.Add(treeNode);
    结果=真;
    }
    }
    返回结果;
    }
    
    您在这里所做的是获取一棵树,并将该树中的每个节点投影到其他树中,同时保持该树的结构。这实际上相当简单。只需创建一个查找,将每个节点映射到其所有子节点,然后遍历每个节点,查找“您自己”然后将查找中的所有子节点添加到新节点:

    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);
    
    var root=new TreeNode[]{};//要映射的原始数据
    var lookup=root.SelectMany(node=>node)
    .ToLookup(node=>node.Parent,node=>new
    {
    节点,
    UINode=新的树节点(node.Data),
    });
    foreach(lookup.SelectMany(group=>group)中的变量对)
    foreach(查找[pair.node]中的变量子级)
    pair.UINode.Nodes.Add(child.UINode);
    TreeView视图=新建TreeView();
    foreach(var root in lookup[null])//假设父节点为空