Как эффективно удалить отмеченные элементы из TreeView? - PullRequest
7 голосов
/ 05 мая 2009

Как можно легко перебрать все узлы TreeView, изучить их свойство .Checked, а затем удалить все проверенные узлы?

Это кажется простым, но вы не должны изменять коллекцию, через которую вы выполняете итерацию, исключая возможность цикла "foreach". (Вызов .Nodes.Remove изменяет коллекцию.) Если это сделать, то эффект состоит в том, что удаляется только около половины узлов .Checked.

Даже если использовать два прохода: сначала создать список временных индексов, а затем удалить по индексу на втором проходе - индексы будут меняться при каждом удалении, нарушая целостность списка индексов.

Итак, какой самый эффективный способ сделать это?

Вот пример кода, который выглядит хорошо, но на самом деле удаляет только примерно половину .Checked узлов.

            foreach (TreeNode parent in treeView.Nodes)
            {
                if (parent.Checked)
                {
                    treeView.Nodes.Remove(parent);
                }
                else
                {
                    foreach (TreeNode child in parent.Nodes)
                    {
                        if (child.Checked) parent.Nodes.Remove(child);
                    }
                }
            }

(Да, намерение состоит только в том, чтобы обрезать узлы из дерева, которое имеет глубину в два уровня.)

Ответы [ 4 ]

7 голосов
/ 05 мая 2009

Попробуйте пройти через узлы задом наперед. Таким образом, ваш индекс не увеличится после размера вашего узла:

for( int ndx = nodes.Count; ndx > 0; ndx--)
{
  TreeNode node = nodes[ndx-1];
  if (node.Checked)
  {
     nodes.Remove(node);
  }
   // Recurse through the child nodes...
}
6 голосов
/ 05 мая 2009

Это удалит узлы после их перечисления и может быть использовано рекурсивно для n-уровневых узлов.

void RemoveCheckedNodes(TreeNodeCollection nodes)
{
    List<TreeNode> checkedNodes = new List<TreeNode>();

    foreach (TreeNode node in nodes)
    {
        if (node.Checked)
        {
            checkedNodes.Add(node);
        }
        else
        {
            RemoveCheckedNodes(nodes.ChildNodes);
        }
    }

    foreach (TreeNode checkedNode in checkedNodes)
    {
        nodes.Remove(checkedNode);
    }
}
3 голосов
/ 05 мая 2009

Если вы хотите сделать это эффективно, вам нужно отслеживать проверенные узлы, поскольку они проверены. Сохраните отмеченные узлы дерева в списке (и удалите их, когда они не проверены).

Если у вас есть уникальный ключ и множество узлов для отслеживания, вы можете рассмотреть и словарь. Но если вы имеете дело только с 10-50, это, вероятно, не будет иметь большого значения.

Тогда вместо того, чтобы проходить по всему дереву, вы просто зацикливаете свой (меньший) список узлов.

1 голос
/ 05 мая 2009

Пока вы выполняете итерацию, вы можете создать новый список непроверенных элементов, а затем повторно привязать свое древовидное представление к этому новому списку (исключая старый).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...