2011-05-23 371 views
1

我试图从XmlDocument填充一个树形视图。 树的根被设置为“脚本”,并且从根目录开始,下一级应该是XML脚本中的“部门”。我可以从XML文档中获取数据没有问题。我的问题是,当循环遍历XmlDocument并向根节点添加节点时,我想确保如果一个部门已经在树视图中,那么它不会再被添加。我还应该补充一点,每个部门都有一个需要成为部门子节点的脚本列表。C#TreeView检查节点是否存在

到目前为止我的代码是:

 XmlDocument xDoc = new XmlDocument(); 
     xDoc.LoadXml(scriptInformation); 
     TreeNode t1; 
     TreeNode rootNode = new TreeNode("Script View"); 
     treeView1.Nodes.Add(rootNode); 
     foreach (XmlNode node in xDoc.SelectNodes("//row")) 
     { 
      t1 = new TreeNode(node["DEPARTMENT"].InnerXml); 
      //How to check if node already exists in treeview? 



     } 

感谢。

回答

2
if(treeView1.Nodes.ContainsKey("DEPARTMENT")){ 
//... 
} 

编辑:递归方法:

bool exists = false; 
     foreach (TreeNode node in treeView1.Nodes) { 
      if (NodeExists(node, "DEPARTMENT")) 
       exists = true; 
     } 
    private bool NodeExists(TreeNode node, string key) { 
     foreach (TreeNode subNode in node.Nodes) { 
      if (subNode.Text == key) { 
       return true; 
      } 
      if (node.Nodes.Count > 0) { 
       NodeExists(node, key); 
      } 
     } 
     return false; 
    } 
+0

执行查找。我不相信这是完全递归的。实际上,它只会搜索直接的子节点。 – Yuck 2011-05-23 12:29:31

+0

在这种情况下,可以很容易地创建递归方法。 – Vale 2011-05-23 12:38:38

+0

if(subNode.Text.Equals(key)) return subNode; (subNode.Nodes.Count> 0) { } NodeExists(subNode,key); } – Akvel 2012-02-08 17:06:31

0

这取决于您输入的结构。由于您没有显示如何正确添加子节点,因此我只能将您指向ContainsNodes属性的Nodes属性的方法,即treeView1本身或您添加的任何子节点。您应该使用Add方法的重载来指定密钥名称以简化查找。

1

根据您的XML文件的大小,你可以考虑使用相关的List快速查找。当您将每个节点添加到TreeView时,也将其添加到List

1

你可以做这样的事情:

TreeNode parentNode = t1.Parent; 
if (parentNode != null} 
{ 
    if(parentNode.Nodes.Cast<TreeNode>().ToList().Find(t => t.Text.Equals(node["DEPARTMENT"].InnerXml) == null) 
    { 
     //Add node 
    } 
} 
else 
{ 
    bool isFound = true; 
    if (treeView1.Nodes.Cast<TreeNode>().ToList().Find(t => t.Text.Equals(node["DEPARTMENT"].InnerXml) == null) 
    { 
     isFound = false; 
    } 

    if(!isFound) 
    { 
     //Add node 
    } 
} 
1

如果你的XML文档有一组结构,其中“部门”总是以1被索引;

即:

index:[0] Scripts 
    index:[1] Department 
     index:[2] Script 
    index:[1] Department2 
     index:[2] Script 

然后,你可以封装下面的代码,其中“名称”是一个字符串参数和返回值类型为布尔的方法。

foreach (TreeNode node in uxTreeView.Nodes[0].Nodes) { 
    if (node.Name.ToLower() == name.ToLower()) { 
     return true; 
    } 
} 
return false; 

想法是每次在创建TreeNode之前遇到Xml中的'Department'节点时,都会调用该函数。

完整的示例:

private bool DepartmentNodeExists(string name) { 
    foreach (TreeNode node in uxTreeView.Nodes[0].Nodes) { 
     if (node.Name.ToLower() == name.ToLower()) { 
      return true; 
     } 
    } 
    return false; 
} 

最后,容易方式:

private bool DepartmentNodeExists(string name) { 
    if (uxTreeView.Nodes[0].ContainsKey(name)) { 
     return true; 
    } 
    else { 
     return false; 
    } 
} 

这些都只是重构和封装到自己的命名方法,你当然可以只叫:

if (uxTreeView.Nodes[0].ContainsKey(name)) { 
    // do not create TreeNode 
} 

...在您的解析过程中的XML。 PS。这些示例都假定您已经创建了TreeView中的第一个根节点并将其添加到了TreeView中。

1

不知道有关文档结构的...
你不能使用LINQ到XML,加载文档,并获得不同的行(行=部门?),并考虑只有那些创建TreeNode的元素?它比试图找到具有这种文本的节点是否已被添加更有效。 例如:

var rows =  ( from row in XDocument.Load(document).Root.Elements("row") 
        select row 
       ).Distinct(new SampleElementComparerOnNameAttribute()); 

这里EqualityComparer是在 “名称” 属性值假设文档结构做成

<rows><row name='dep1'><script>script1</script><script>script2</script></row><row name='dep1'><script>script3</script><script>script4</script></row></rows> 
1

我用,

string department = node["DEPARTMENT"].InnerXml; 
TreeNode node = parentNode.Nodes[department] ?? parentNode.Nodes.Add(department, department); 

该行保证一个价值部门的查询将首先完成,如果没有找到它会创建它。您必须在Add()中进行双重输入,因此它将具有一个键值,您可以使用.Nodes[department].