永无止境的程序

..::[......]::..

导航

你可能不太了解的TreeNode

用了很长时间的TreeView,TreeNode,才发现你不了解他的话,有时候会很不听话的
因为某种需要,我要删除某节点的所有子节点,但是要保持对所有节点的引用,因此不能是用Nodes.Clear()方法来做,所以我遍历该节点的所有子节点,将每个节点从集合中拉出来,扔到一个ArrayList里(当然可以先复制所有节点,然后调用Clear()方法,但我当时没有这么做,否则的话也不会出现下面的问题了)
代码:

    ArrayList list = new ArrayList();
    TreeNode root 
= new TreeNode();
    root.Nodes.Add(
new TreeNode("1"));
    root.Nodes.Add(
new TreeNode("2"));
    root.Nodes.Add(
new TreeNode("3"));
    root.Nodes.Add(
new TreeNode("4"));
    
foreach( TreeNode curNode in root.Nodes){
        Console.WriteLine(curNode.Text);
        curNode.Remove();
        list.Add(curNode);
    }

这段代码好象没什么问题,编译也通过,可是运行出现下面异常:

Unhandled Exception: System.NullReferenceException: Object reference not set to an instance of an object.


再看控制台输出,竟然是
1
3
4
4

显然,他跳过了第二个TreeNode,而在最后循环到最后一个TreeNode的时候curNode指向的是已经从父节点Remove掉的节点,好象很奇怪。增加几个节点:

    root.Nodes.Add(new TreeNode("1"));
    root.Nodes.Add(
new TreeNode("2"
));
    root.Nodes.Add(
new TreeNode("3"
));
    root.Nodes.Add(
new TreeNode("4"
));
    root.Nodes.Add(
new TreeNode("5"
));
    root.Nodes.Add(
new TreeNode("6"
));
    root.Nodes.Add(
new TreeNode("7"
));
    root.Nodes.Add(
new TreeNode("8"
));
    root.Nodes.Add(
new TreeNode("9"
));
    root.Nodes.Add(
new TreeNode("10"
));

仍然异常,这次再看输出,发现是
1
3
5
7
9
10
10
原来Remove操作影响了循环,每次Remove都减少一个节点,于是curNode总是指向后一个节点而不是下一个节点,所以循环会跳过偶数项了。这个理解了,又有新的问题:当循环遍历最后一个节点10之后,仍然往下走,而不是跳出循环,前面的出现异常显然是在第二次Remove节点10的时候抛出的,为什么会再次引用节点10呢,难道他越界后就不停的循环引用节点10了?
那么我们再改代码,在Remove()之前判断,:

    if(curNode.Parent == root){
        curNode.Remove();
    }

输出是:
1
3
5
7
9
10
10
10
10
10

可以见得Remove 操作虽然改变了循环所引用的对象,但是却没有改变循环的次数,他仍然按照Remove之前的循环次数循环,所以会引发前面的异常。

下面给出我的解决方案:

    foreach(TreeNode curNode in root.Nodes){
        list.Add(root.Nodes[0
]);
        root.Nodes[
0
].Remove();
    }

但这样的话curNode声明没有用到,所以改用for,并且逆向循环。

    for (int i=root.Nodes.Count; -->=0;){
        Console.WriteLine(root.Nodes[i].Text);
            root.Nodes.RemoveAt(i);
    }


或者用前面提到的先复制再清除的方法

   TreeNodeCollection myTreeNodeCollection = myTreeViewBase.Nodes;
   TreeNode[] myTreeNodeArray = new
 TreeNode[myTreeViewBase.Nodes.Count];
   myTreeViewBase.Nodes.CopyTo(myTreeNodeArray,0
);
   myTreeViewBase.Nodes.Clear();

posted on 2004-09-27 11:35  AlleNny  阅读(2442)  评论(0)    收藏  举报