树搜索算法从这里开始:
// stack is used to traverse the tree iteratively.
Stack<TreeNode> stack = new Stack<TreeNode>();
private void treeView1_AfterCheck(object sender, TreeViewEventArgs e)
{
TreeNode selectedNode = e.Node;
bool checkedStatus = e.Node.Checked;
// suppress repeated even firing
treeView1.AfterCheck -= treeView1_AfterCheck;
// traverse children
stack.Push(selectedNode);
while(stack.Count > 0)
{
TreeNode node = stack.Pop();
node.Checked = checkedStatus;
System.Console.Write(node.Text + ", ");
if (node.Nodes.Count > 0)
{
ICollection tnc = node.Nodes;
foreach (TreeNode n in tnc)
{
stack.Push(n);
}
}
}
//traverse parent
while(selectedNode.Parent!=null)
{
TreeNode node = selectedNode.Parent;
node.Checked = checkedStatus;
selectedNode = selectedNode.Parent;
}
// "suppress repeated even firing" ends here
treeView1.AfterCheck += treeView1_AfterCheck;
string str = string.Empty;
}
驱动程序
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
#region MyRegion
private void button1_Click(object sender, EventArgs e)
{
TreeNode a = new TreeNode("A");
TreeNode b = new TreeNode("B");
TreeNode c = new TreeNode("C");
TreeNode d = new TreeNode("D");
TreeNode g = new TreeNode("G");
TreeNode h = new TreeNode("H");
TreeNode i = new TreeNode("I");
TreeNode j = new TreeNode("J");
TreeNode k = new TreeNode("K");
TreeNode l = new TreeNode("L");
TreeNode m = new TreeNode("M");
TreeNode n = new TreeNode("N");
TreeNode o = new TreeNode("O");
TreeNode p = new TreeNode("P");
TreeNode q = new TreeNode("Q");
TreeNode r = new TreeNode("R");
TreeNode s = new TreeNode("S");
TreeNode t = new TreeNode("T");
TreeNode u = new TreeNode("U");
TreeNode v = new TreeNode("V");
TreeNode w = new TreeNode("W");
TreeNode x = new TreeNode("X");
TreeNode y = new TreeNode("Y");
TreeNode z = new TreeNode("Z");
k.Nodes.Add(x);
k.Nodes.Add(y);
l.Nodes.Add(s);
l.Nodes.Add(t);
l.Nodes.Add(u);
n.Nodes.Add(o);
n.Nodes.Add(p);
n.Nodes.Add(q);
n.Nodes.Add(r);
g.Nodes.Add(k);
g.Nodes.Add(l);
i.Nodes.Add(m);
i.Nodes.Add(n);
j.Nodes.Add(b);
j.Nodes.Add(c);
j.Nodes.Add(d);
a.Nodes.Add(g);
a.Nodes.Add(h);
a.Nodes.Add(i);
a.Nodes.Add(j);
treeView1.Nodes.Add(a);
treeView1.ExpandAll();
button1.Enabled = false;
}
#endregion
期望发生的事情:
请查看应用程序的屏幕截图。选中A、G、L和T。如果我取消选择,比如说L,那么:
- T应该被取消选择,因为T是L的子节点。
- G和A应该被取消选择,因为它们将没有剩余的子节点。
实际发生的事情:
如果我单击任何节点,则此应用程序代码正常工作。如果我双击一个节点,该节点将变为选中/取消选中状态,但是父节点和子节点上不会反映出相同的更改。
双击还会使应用程序冻结一段时间。
我该如何解决这个问题并获得期望的行为?
AfterCheck
事件而不是鼠标事件。同时请参考这篇帖子。 - Reza AghaeiAfterCheck
事件处理程序。这样,双击的第一次点击会将其关闭,而双击的第二次点击会在第一次点击的处理过程中发生。由于已经断开了事件处理程序,因此不会触发第二次点击的事件处理程序。您可以考虑使用布尔标志代替断开处理程序,并将每个“点击”添加到单击事件堆栈中。 - Sam Axe