Reputation: 41
How do i check/uncheck all child items in TreeView? Probably error happened when one of items become to selected state and child items checked/unchecked buggy.
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();
}
Upvotes: 4
Views: 18550
Reputation: 23
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;
}
}
}
Upvotes: 0
Reputation: 11
The solution that I've figured out was the following:
To perform the selection I used 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);
Then to handle the event selection I extended the TreeView class:
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;
}
}
In the host control, you can hook the pre and post cascade events and iterate over all checked/unchecked tree nodes avoiding a lot of cross event firing. You control the cascade via some container.
I got the ForEach to IEnumerable from the following an implementation from the web:
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);
}
}
Good Luck!
Upvotes: 1
Reputation: 570
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);
}
}
}
Upvotes: 0
Reputation: 13931
Here is an answer (from Hans Passant):
Winforms treeview, recursively check child nodes problem
Im writing it as answer, not comment to make it easier to find.
Upvotes: 0
Reputation: 18843
using your code that you have in the Form_Load keep that code it works and add these 2 methods in your code
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;
}
}
Upvotes: 5