2017-02-17 3 views
1

Я пытаюсь выполнить поиск TreeView для определенной строки, как только я нашел индекс узла, я хочу вернуть его индекс и изменить задний цвет этого конкретного узла, однако мой текущий код, кажется, не будет возвращаться любые матчи, если это не корневой узел:Поиск древовидной структуры для определенной строки

private void ApplyRulesetColors() 
    { 
     foreach (var rule in dictOverwriteEntries) 
     { 
      int iResultIndex = SearchTreeView(rule.Key, tvDirectoryStructure.Nodes); 

      if (iResultIndex > -1) 
      { 
       switch (rule.Value) 
       { 
        case Operations.Overwrite: 
         tvDirectoryStructure.Nodes[iResultIndex].BackColor = Color.Red; 
         break; 
        case Operations.Delete: 
         break; 
        case Operations.None: 
         break; 
        default: 
         break; 
       } 
      } 
     } 
    } 

Это функция, которая должна быть поиск в TreeView:

private int SearchTreeView(string p_sSearchTerm, TreeNodeCollection p_Nodes) 
    { 
     foreach (TreeNode node in p_Nodes) 
     { 
      if (node.Text == p_sSearchTerm) 
      { 
       return node.Index; 
      } 

      if (node.Nodes.Count > 0) 
       SearchTreeView(p_sSearchTerm, node.Nodes); 
     } 

     return -1; 
    } 

в тот момент, когда будет только когда-либо сопоставить значение корневого узла и вернуть 0, хотя (насколько я могу судить) он должен искать по всему дереву, включая дочерние узлы.

спасибо.

+2

Wouldnt вы хотите "вернуть SearchTreeView (p_sSearchTerm, node.Nodes);" ? в противном случае он ест возвращаемое значение – BugFinder

+1

Вы можете использовать ['Найти'] (https://msdn.microsoft.com/en-us/library/system.windows.forms.treenodecollection.find (v = vs.110) .aspx) метода 'TreeView' для поиска узлов на основе их свойства' Name'. Кроме того, если вы хотите выполнить более сложный поиск, вы можете использовать метод расширения '' Descendants' '(http://stackoverflow.com/a/32360956/3110834). Вы можете увидеть пример обоих методов [здесь] (http://stackoverflow.com/a/34228733/3110834). –

ответ

1

Есть две проблемы в вашем коде:

  1. Вы не возвращают результат рекурсивного вызова, но -1, если узел не был найден у детей корневого узла.
  2. Вы возвращаетесь узлы Index, что является индексом в родительских детях коллекции узла, не глобальных индекса.

Я предлагаю вместо этого вернуть TreeNode. Измените метод так:

private TreeNode SearchTreeView(string p_sSearchTerm, TreeNodeCollection p_Nodes) 
{ 
    foreach (TreeNode node in p_Nodes) 
    { 
     if (node.Text == p_sSearchTerm) 
      return node; 

     if (node.Nodes.Count > 0) 
     { 
      TreeNode child = SearchTreeView(p_sSearchTerm, node.Nodes); 
      if (child != null) return child; 
     } 
    } 

    return null; 
} 

И использовать его так:

private void ApplyRulesetColors() 
{ 
    foreach (var rule in dictOverwriteEntries) 
    { 
     TreeNode resultNode = SearchTreeView(rule.Key, tvDirectoryStructure.Nodes); 

     if (resultNode != null) 
     { 
      switch (rule.Value) 
      { 
       case Operations.Overwrite: 
        resultNode.BackColor = Color.Red; 
        break; 
       case Operations.Delete: 
        break; 
       case Operations.None: 
        break; 
       default: 
        break; 
      } 
     } 
    } 
} 

Заметим, однако, что этот код будет найти только первый узел согласования. Я не знаю, может ли ваше дерево содержать несколько узлов с тем же Text. В этом случае вы должны использовать другое свойство для идентификации узла.

1

Вам необходимо вернуть TreeNode сам не его индекс, так как индекс относится к родительскому элементу расположенного узла. Кроме того, ваш рекурсивный SearchTreeView не возвращает элемент, когда он нашел его во время рекурсивного вызова. Приведенный ниже код будет работать и возвращать TreeNode сам, который вы можете по своему вкусу.

Возможно, вы захотите узнать, что ваш подход неэффективен, так как вам нужно итерировать дерево столько раз, сколько у вас есть правила в вашем списке. Это может быть более эффективно, если вы повторяете одно дерево, а затем сопоставляете правила для каждого узла в списке. Ваш код может быть хороший случай применить Visitor картина: http://www.dofactory.com/net/visitor-design-pattern

В любом случае, здесь правильно SearchTreeView:

private TreeNode SearchTreeView(string p_sSearchTerm, TreeNodeCollection p_Nodes) 
{ 
    foreach (TreeNode node in p_Nodes) 
    { 
     if (node.Text == p_sSearchTerm) 
     { 
      return node; 
     } 

     if (node.Nodes.Count > 0) 
     { 
      var result = SearchTreeView(p_sSearchTerm, node.Nodes); 
      if (result != null) 
      { 
       return result; 
      } 
     } 
    } 

    return null; 
} 
Смежные вопросы