TreeView 全选/取消所有子项

4
如何在TreeView中检查/取消选中所有子项? 可能会出现错误,当其中一个项目变为选定状态时,子项的选中/取消选中会出现故障。 链接到VS 2010项目+Exe YOUTUBE上的视频
private void Form1_Load(object sender, EventArgs e)
    {
        treeView1.CheckBoxes = true;
        treeView1.BeginUpdate();
        treeView1.Nodes.Add("1111");
        treeView1.Nodes[0].Nodes.Add("2222");
        treeView1.Nodes[0].Nodes.Add("2222");
        treeView1.Nodes[0].Nodes.Add("2222");
        treeView1.Nodes[0].Nodes.Add("2222");
        treeView1.Nodes[0].Nodes[1].Nodes.Add("3333");
        treeView1.Nodes[0].Nodes[1].Nodes[0].Nodes.Add("4444");
        treeView1.Nodes[0].Nodes[1].Nodes[0].Nodes.Add("4444");
        treeView1.Nodes[0].Nodes[1].Nodes[0].Nodes.Add("4444");
        treeView1.EndUpdate();

        treeView1.ExpandAll();
    }

    private void treeView1_AfterCheck(object sender, TreeViewEventArgs e)
    {
        treeView1.BeginUpdate();

        foreach (TreeNode Node in e.Node.Nodes)
        {
            Node.Checked = e.Node.Checked;
        }

        treeView1.EndUpdate();
    }

如果需要检查所有子节点,那么就要递归地进行。 - Federico Berasategui
你应该阅读TreeView类MSDN页面的备注部分 - Austin Salonen
Andrey,你需要做一些递归调用的事情,例如:public void UncheckAllNodes(TreeNodeCollection nodes) { foreach (TreeNode node in nodes) { node.Checked = false; CheckChildren(node, false); } } - MethodMan
对于CheckChildren(node,false),请执行以下操作:private void CheckChildren(TreeNode rootNode, bool isChecked) { foreach (TreeNode node in rootNode.Nodes) { CheckChildren(node, isChecked); node.Checked = isChecked; } } - MethodMan
@AndreyPetrovich,你解决了你的问题吗?我也遇到了同样的情况... - Kamil
显示剩余12条评论
5个回答

5

使用您在Form_Load中已有的代码,保留该代码,然后将这两个方法添加到您的代码中。

private void Form1_Load(object sender, EventArgs e)
{
    treeView1.CheckBoxes = true;
    treeView1.BeginUpdate();
    treeView1.Nodes.Add("1111");
    treeView1.Nodes[0].Nodes.Add("2222");
    treeView1.Nodes[0].Nodes.Add("2222");
    treeView1.Nodes[0].Nodes.Add("2222");
    treeView1.Nodes[0].Nodes.Add("2222");
    treeView1.Nodes[0].Nodes[1].Nodes.Add("3333");
    treeView1.Nodes[0].Nodes[1].Nodes[0].Nodes.Add("4444");
    treeView1.Nodes[0].Nodes[1].Nodes[0].Nodes.Add("4444");
    treeView1.Nodes[0].Nodes[1].Nodes[0].Nodes.Add("4444");
    treeView1.EndUpdate();
    treeView1.ExpandAll();
}

private void treeView1_AfterCheck(object sender, TreeViewEventArgs e)
{
    foreach (TreeNode childNode in e.Node.Nodes)
    {
        childNode.Checked = e.Node.Checked;
    }
}

DJ KRAZE那样并没有帮助。所以我制作了一个视频来向您展示问题所在。 http://www.youtube.com/watch?v=kviRgkpUiMs 同时,我修复了视频链接。 - Andrey Petrovich
我提供了一个更新的版本,希望这可以解决你的问题。它也能正常工作,这是一个更干净的代码版本给你。 - MethodMan

1
我想到的解决方案如下:
  • 使用Linq执行选择:

    if (e.Node.Nodes.Count > 0) e.Node.Nodes.Cast<TreeNode>().Where(tnc => tnc.Checked != e.Node.Checked).ForEach(tn => tn.Checked = e.Node.Checked);

  • 然后,为了处理事件选择,我扩展了TreeView类: public class MyTV : TreeView { protected bool TopOfCascade; TreeNode startNode; public Action FinishedCheckEventsDelegate; public Action InitiateCascadeCheckEventsDelegate; public MyTV() : base() { TopOfCascade = false; startNode = null; } protected override void OnBeforeCheck(TreeViewCancelEventArgs e) { base.OnBeforeCheck(e); if (!TopOfCascade && !e.Cancel) { TopOfCascade = true; startNode = e.Node; if (InitiateCascadeCheckEventsDelegate != null) InitiateCascadeCheckEventsDelegate(); } } protected override void OnAfterCheck(TreeViewEventArgs e) { base.OnAfterCheck(e); if (startNode == e.Node && e.Action != TreeViewAction.Unknown) { if (FinishedCheckEventsDelegate != null) FinishedCheckEventsDelegate(); TopOfCascade = false; startNode = null; } } 在主控件中,您可以钩住级联事件的前后,并迭代所有已选/未选中的树节点,避免大量交叉事件触发。通过一些容器来控制级联。

我从网上找到了以下实现,将ForEach转换为IEnumerable:
public static void ForEach<T>(this IEnumerable<T> source, Action<T> action)
{
  if (source == null) throw new ArgumentNullException("source");
  if (action == null) throw new ArgumentNullException("action");
  foreach (T item in source)
  {
    action(item);
  }
}

祝你好运!


0
    private void treeView1_AfterCheck(object sender, TreeViewEventArgs e)
    {

        if (e.Action != TreeViewAction.Unknown)
        {
            if (e.Node.Nodes.Count > 0)
            {
                /* Calls the CheckAllChildNodes method, passing in the current 
                Checked value of the TreeNode whose checked state changed. */
                this.CheckAllChildNodes(e.Node, e.Node.Checked);
            }

        }
    }

   private void CheckAllChildNodes(TreeNode treeNode, bool nodeChecked)
    {
        foreach (TreeNode node in treeNode.Nodes)
        {
            node.Checked = nodeChecked;
            if (node.Nodes.Count > 0)
            {
                // If the current node has child nodes, call the CheckAllChildsNodes method recursively. 
                this.CheckAllChildNodes(node, nodeChecked);
            }
        }
    }

0

0
    private void CheckAllChildNodes(TreeNode treeNode, bool nodeChecked)
    {
        foreach (TreeNode node in treeNode.Nodes)
        {
            node.Checked = nodeChecked;
            if (node.Nodes.Count > 0)
            {
                this.CheckAllChildNodes(node, nodeChecked);
            }
        }
    }
    private void treeView_AfterCheck(object sender, TreeViewEventArgs e)
    {
        if (e.Action != TreeViewAction.Unknown)
        {
            if (e.Node.Nodes.Count > 0)
            {
                if (!e.Node.Checked)
                {
                    this.CheckAllChildNodes(e.Node, e.Node.Checked);
                }
            }
        }

        if (e.Node.Parent != null)
        {
            TreeNode n = e.Node;
            while (n.Parent != null)
            {
                if (n.Checked)
                {
                    n.Parent.Checked = true;
                }
                n = n.Parent;
            }
        }

    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接