트리 뷰에서 확인 된 항목을 효율적으로 삭제하는 방법은 무엇입니까?
문제
TreeView의 모든 노드를 쉽게 반복하고. 점검 된 속성을 검사 한 다음 확인 된 모든 노드를 삭제할 수있는 방법은 무엇입니까?
간단 해 보이지만 반복하는 컬렉션을 수정해서는 안됩니다. "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 만 다루고 있다면 아마 큰 차이를 만들지 않을 것입니다.
그런 다음 전체 트리를 통해 반복하는 대신 (작은) 노드 목록을 통해 루프를 반복합니다.
반복하는 동안 선택되지 않은 새 항목 목록을 구성한 다음 TreeView를 해당 새 목록으로 다시 바꾸어 놓을 수 있습니다 (이전 목록을 폐기).