2009-05-05 5 views
7

Làm cách nào để dễ dàng lặp qua tất cả các nút trong TreeView, kiểm tra thuộc tính .Checked của chúng và sau đó xóa tất cả các nút đã chọn?Làm thế nào để xóa một cách hiệu quả các mục được kiểm tra từ một TreeView?

Có vẻ đơn giản, nhưng bạn không được phép sửa đổi bộ sưu tập mà qua đó bạn đang lặp lại, loại bỏ khả năng xảy ra vòng lặp "foreach". (The .Nodes.Remove gọi là sửa đổi bộ sưu tập.) Nếu điều này là cố gắng, hiệu quả là chỉ có khoảng một nửa các nút .Checked được loại bỏ.

Ngay cả khi người dùng sử dụng hai lần vượt qua: đầu tiên tạo danh sách các chỉ mục tạm thời và sau đó loại bỏ chỉ mục trên đèo thứ hai - các chỉ mục sẽ thay đổi theo từng loại bỏ, đánh giá tính toàn vẹn của danh sách chỉ mục.

Vì vậy, cách hiệu quả nhất để làm điều này là gì?

Dưới đây là một ví dụ về mã mà có vẻ tốt, nhưng thực chất chỉ loại bỏ khoảng một nửa số các nút .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); 
        } 
       } 
      } 

(Vâng, mục đích duy nhất là để prune nút từ một cái cây đó là hai Ở mức độ sâu.)

Trả lời

6

Điều này sẽ loại bỏ các nút sau khi liệt kê chúng và có thể được sử dụng đệ quy cho các cấp n nút.

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); 
    } 
} 
1

Trong khi lặp lại, bạn có thể tạo danh sách các mục chưa được kiểm tra mới và sau đó liên kết lại ảnh treeview của bạn với danh sách mới đó (loại bỏ ảnh cũ).

7

Thử đi qua các nút ngược. Bằng cách đó, chỉ mục của bạn không tăng quá kích thước nút của bạn:

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

Đây là phương pháp hiệu quả nhất. – Romias

+0

Câu hỏi cũ, nhưng +1 cho đây là phương pháp hiệu quả nhất. – TimFoolery

+0

Xem lại điều này ... một vài sửa đổi sẽ làm cho nó nhanh hơn một chút ... tạo ra các thay đổi sau trong tiêu đề vòng lặp: 'int ndx = nodes.Count-1' và' ndx> = 0' sẽ cho phép bạn để tránh -1 xảy ra trong mỗi lần truyền qua vòng lặp. Trong kế hoạch lớn của sự vật, một vài phép trừ thêm sẽ không có ý nghĩa gì nhiều, nhưng hey ... tại sao không? – TimFoolery

3

Nếu bạn muốn thực hiện hiệu quả, bạn cần phải theo dõi các nút đã chọn khi chúng được chọn. Lưu trữ các nút cây được kiểm tra trong một danh sách (và loại bỏ chúng khi chúng được bỏ chọn).

Nếu bạn có khóa duy nhất và rất nhiều nút để theo dõi bạn cũng có thể xem xét từ điển. Nhưng nếu bạn chỉ đối phó với 10-50 thì có lẽ nó sẽ không tạo nên sự khác biệt lớn.

Sau đó, thay vì lặp qua toàn bộ cây bạn chỉ cần lặp qua danh sách các nút (nhỏ hơn) của bạn.