使用泛型委托简化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);
}
没有公共变量,方法容易理解,逻辑简单容易维护。如有疏漏,请不吝指正。

浙公网安备 33010602011771号