TreeView检查/取消检查所有子项
本文关键字:检查 取消 TreeView | 更新日期: 2023-09-27 17:57:54
如何选中/取消选中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();
}
使用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;
}
}
我找到的解决方案如下:
-
为了进行选择,我使用了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; } }
在宿主控件中,您可以挂接级联前和级联后的事件,并在所有已检查/未检查的树节点上迭代,从而避免大量跨事件触发。您可以通过某个容器控制级联。
我从以下web实现中获得了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);
}
}
祝你好运!
以下是答案(来自Hans Passant):
Winforms树视图,递归检查子节点问题
我把它写为答案,而不是评论,这样更容易找到。
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);
}
}
}
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;
}
}
}