Как эффективно удалить отмеченные элементы из TreeView?
Вопрос
Как можно легко перебрать все узлы 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, это, вероятно, не будет иметь большого значения.
Затем, вместо того, чтобы проходить по всему дереву, вы просто зацикливаете свой (меньший) список узлов.
Пока вы выполняете итерацию, вы можете создать новый список непроверенных элементов, а затем повторно привязать свое древовидное представление к этому новому списку (отбрасывая старый).