Advanced User Interface Controls and Components
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.
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