Как эффективно удалить отмеченные элементы из TreeView?

StackOverflow https://stackoverflow.com/questions/825323

Вопрос

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

Это кажется простым, но вы не должны изменять коллекцию, через которую вы выполняете итерации, исключая возможность & forech; 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);
                    }
                }
            }

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

Это было полезно?

Решение

Это удалит узлы после их перечисления и может быть использовано рекурсивно для 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);
    }
}

Другие советы

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

for( int ndx = nodes.Count; ndx > 0; ndx--)
{
  TreeNode node = nodes[ndx-1];
  if (node.Checked)
  {
     nodes.Remove(node);
  }
   // Recurse through the child nodes...
}

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top