使用泛型委托简化TreeView递归
如以下代码所示,方法内有整型变量k,声明泛型委托hanlder并在内部对k进行自增操作,打印k得到101。
static void Main(string[] args) { int k = 100; Action handler = () => k++; handler(); Console.WriteLine(k); }
WinForm中的TreeView常常要解决类似“父节点与子节点勾选”问题,注册TreeView.AfterCheck事件并添加递归方法很容易实现,现在添加需求,要求计算所有勾选状态TreeView的子节点;再添加需求,现在有第三方TreeView能实现类似Win7中“子节点非全选状态下父节点半选的状态”,现需要对半选节点计数……
基本上需要为每个需求写上一个方法并添加out或ref修饰的计数参数或添加公共变量,代码不是那么好看了。现添加两个方法:
private void treeNodeWalkSequence(TreeNode treeNode, Action<TreeNode> handler) { handler(treeNode); foreach (TreeNode node in treeNode.Nodes) { treeNodeWalkSequence(node, handler); } }
private void treeNodeWalkReversed(TreeNode treeNode, Action<TreeNode> handler) { handler(treeNode); if (treeNode.Parent != null) { treeNodeWalkReversed(treeNode.Parent, handler); } }
treeNodeWalkSequence实现了子节点的前序遍历,treeNodeWalkReversed实现了父节点的回溯。
对父子节点勾选的需求实现如下:
private void treeView1_AfterCheck(object sender, TreeViewEventArgs e) { if (e.Action != TreeViewAction.Unknown) { Action<TreeNode> handler = treeNode => treeNode.Checked = e.Node.Checked; treeNodeWalkSequence(e.Node, handler); Action<TreeNode> handler2 = treeNode => { if (treeNode.Parent != null) { bool flag = true; foreach (TreeNode sibling in treeNode.Parent.Nodes) { if (!sibling.Checked) { flag = false; break; } } treeNode.Parent.Checked = flag; } }; treeNodeWalkReversed(e.Node, handler2); } }
对勾选状态的节点计数实现如下:
private void button1_Click(object sender, EventArgs e) { int n = 0; Action<TreeNode> handler = treeNode => { if (treeNode.Checked) { n++; } }; //or //Action<TreeNode> handler = treeNode => n += treeNode.Checked ? 1 : 0; foreach (TreeNode treeNode in treeView1.Nodes) { treeNodeWalkSequence(treeNode, handler); } label1.Text = String.Format("count: {0}", n); }
没有公共变量,方法容易理解,逻辑简单容易维护。如有疏漏,请不吝指正。