使用泛型委托简化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);
}

没有公共变量,方法容易理解,逻辑简单容易维护。如有疏漏,请不吝指正。

posted @ 2012-06-19 17:23  Jusfr  阅读(570)  评论(0编辑  收藏  举报