LIDOR SYSTEMS

Advanced User Interface Controls and Components

Display Three State Checkboxes in TreeView .NET Control

Created: Mar 05, 2009

Updated: Jun 01, 2013

By default the IntegralUI TreeView displays two states of the checkboxes in each node. By setting the CheckMode property to ThreeState, every check box can display one of these three states: Unchecked, Indeterminate and Checked.

treeview with tri-state checkboxes
Download free sample

However, the check box value is not automatically updated for any child or parent node. To do that, the AfterCheck event needs to be handled. Here is how:

At first you need to have a TreeView with some root nodes and child nodes in it. Also nodes must have check box visible and the tri-state mode enabled. In the following code we will create a small tree hierarchy:

private void InitList()

{

// Suspend the treeview layout to increase performance

this.treeView1.SuspendUpdate();

this.treeView1.Nodes.Clear();

 

// Make sure the check boxes are displayed, and they accepts three values

this.treeView1.CheckBoxes = true;

this.treeView1.CheckMode = LidorSystems.IntegralUI.CheckMode.ThreeState;

 

LidorSystems.IntegralUI.Lists.TreeNode node = null;

for (int i = 0; i < 10; i++)

{

// Create a new node

node = new LidorSystems.IntegralUI.Lists.TreeNode("Node " + i.ToString());

 

// Create a child nodes for this node

CreateChildNodes(node, 0);

 

// Add the node as the root node

this.treeView1.Nodes.Add(node);

}

 

// Resume the treeview layout and update the control

this.treeView1.ResumeUpdate();

}

 

private void CreateChildNodes(LidorSystems.IntegralUI.Lists.TreeNode parentNode, int level)

{

//In this example only 2 levels in hierarchy are allowed

if (level == 2)

return;

else

{

LidorSystems.IntegralUI.Lists.TreeNode node = null;

for (int i = 0; i < 3; i++)

{

// Create a new child node

node = new LidorSystems.IntegralUI.Lists.TreeNode("Node " + level.ToString() + i.ToString());

 

// Create a child nodes for this node

CreateChildNodes(node, level + 1);

 

// Add the node to the parent node

parentNode.Nodes.Add(node);

}

}

}

Then by handling the AfterCheck event, we will cycle through child and parent nodes and change the value of their check box. The UpdateChild method is used to change the check box value of the child nodes, while UpdateParent method is used to change the check box value of the parent nodes.

In order to avoid callback internally whenever a value of check box s changed when AfterCheck event is called, we will use a variable which determines whether the event is already called or not.

private bool suspendCallBack = false;

 

. . .

 

private void treeView1_AfterCheck(object sender, LidorSystems.IntegralUI.ObjectEventArgs e)

{

if (!suspendCallBack && e.Object is LidorSystems.IntegralUI.Lists.TreeNode)

{

LidorSystems.IntegralUI.Lists.TreeNode node = (LidorSystems.IntegralUI.Lists.TreeNode)e.Object;

 

// Suspend the further calling of BeforeCheck and AfterCheck events

suspendCallBack = true;

 

// Use this method to update the state for all child nodes of this node

UpdateChild(node);

 

// Use this method to update the state for all parent nodes of this node

UpdateParent(node);

 

// Resume the calling of BeforeCheck and AfterCheck events

suspendCallBack = false;

}

}

 

private void UpdateChild(LidorSystems.IntegralUI.Lists.TreeNode node)

{

// If the parent node is not Indeterminate

// change the state of all child nodes

if (node.CheckState != CheckState.Indeterminate)

{

CheckState state = node.CheckState;

foreach (LidorSystems.IntegralUI.Lists.TreeNode childNode in node.Nodes)

{

if (childNode.Visible)

{

// Change the CheckState of the childNode

childNode.CheckState = state;

 

// Repeat the whole cycle for other child nodes

UpdateChild(childNode);

}

}

}

}

 

private void UpdateParent(LidorSystems.IntegralUI.Lists.TreeNode node)

{

// Hold te number of unchecked and visible nodes

int numUnchecked = 0;

int numVisible = 0;

 

// Let presume that by default that node is checked

CheckState state = CheckState.Checked;

 

// Get the parent node

LidorSystems.IntegralUI.Lists.TreeNode parentNode = node.Parent;

while (parentNode != null)

{

numUnchecked = 0;

numVisible = 0;

 

state = CheckState.Checked;

foreach (LidorSystems.IntegralUI.Lists.TreeNode childNode in parentNode.Nodes)

{

if (childNode.Visible)

{

numVisible++;

// If there is at least one Indeterminate node, exit the loop.

// The state for the parent node will be also Indeterminate

if (childNode.CheckState == CheckState.Indeterminate)

{

state = CheckState.Indeterminate;

break;

}

// Count the unchecked nodes

else if (childNode.CheckState == CheckState.Unchecked)

numUnchecked++;

}

}

 

if (numVisible > 0)

{

// If there are no unchecked nodes and there is at least one indeterminate node,

// that means that all child nodes are checked. So, the parent node will also be Checked

if (numUnchecked == 0 && state != CheckState.Indeterminate)

state = CheckState.Checked;

// If number of visible and unchecked nodes are equal, then parent node will be Unchecked

else if (numUnchecked == numVisible)

state = CheckState.Unchecked;

// In any other case, then parent node will be Indeterminate

else

state = CheckState.Indeterminate;

}

// If there are no visible nodes, the parent node will be unchecked

else

state = CheckState.Unchecked;

 

// Change the CheckState of the parent node,

parentNode.CheckState = state;

 

// Repeat the whole cycle for other parent nodes

parentNode = parentNode.Parent;

}

}

A complete sample project in C# .NET and VB .NET, showing how to create nodes with tri-state checkboxes in TreeView, is available for download from here: TreeView .NET - Three State Checkboxes

Newsletter


Sign-up to our newsletter and you will receive news on upcoming events, latest articles, samples and special offers.
Name: Email: *
*By checking this box, I agree to receive a newsletter from Lidor Systems in accordance with the Privacy Policy. I understand that I can unsubscribe from these communications at any time by clicking on the unsubscribe link in all emails.