Click here to Skip to main content
15,867,594 members
Articles / Desktop Programming / Win32

Tri-State TreeView Control for .NET 1.1

Rate me:
Please Sign up or sign in to vote.
4.75/5 (10 votes)
14 Dec 2007CPOL3 min read 109.6K   4.8K   45   22
Tri-state checkboxes, user-defined state images, disable checkboxes per node...

Screenshot -

Introduction

The TreeView control as implemented by Microsoft in the .NET 1.1 Framework does support checkboxes, but those checkboxes allow only two states: checked or unchecked.

This control is built on top of the TreeView control, and provides some additional functionality that might be useful.

  • Tri-state checkboxes, checked / unchecked / indeterminate state.
  • TriStateTreeView supports custom images for all three states. When not using custom images, default tri-state images are provided. Custom images are configured the same way as the "ImageIndex" and the "SelectedImageIndex" properties, so state images can be added to the ImageList bound to the TreeView using the ImageList property.
  • Checkboxes can be switched off on a per-node basis.
  • The TreeView recognizes two different types of TreeNodes: Containers and Items. They behave differently when child nodes are checked / unchecked.

Background

Some of this code, mostly the wndproc hooks, comes from another sample found on this site. It was a VB.NET sample developed by Carlos J. Quintero dealing with the node fonts: http://www.codeproject.com/KB/cpp/CustomDrawTreeview.aspx. I translated that sample and added my own stuff. Thanks Carlos for sharing your code with us.

Using the code

The sources contain two classes: TriStateTreeView and TriStateTreeNode.

The TriStateTreeNode class exposes an internal property, NodeLineType, which is read by the TriStateTreeView control when it is about to draw the node. When a checkbox has been disabled for a certain node, a dotted line should be drawn to replace that checkbox, in the way the original TreeView would do it.

Enum NodeLineType

The property NodeLineType returns a value of type NodeLineType, which can have three different values:

  • None - No line needs to be drawn
  • Straight - Only a straight line has to be drawn where normally a checkbox would be drawn
  • WithChildren - A straight line must be drawn, and a connecting line to the node's children
C#
internal enum NodeLineType
{
    None,
    Straight,
    WithChildren
}

Class TriStateTreeView

The class TriStateTreeView has been derived from System.Windows.Forms.TreeView, and exposes the additional properties listed below:

  • UseCustomImages - Design or runtime editable. Determines if the TreeView draws the images configured in the ImageList (custom), or the default images.
  • CheckedImageIndex - Index of the image to display when the node is in the Checked state (UseCustomImages must be true).
  • UncheckedImageIndex - Index of the image to display when the node is in the Unchecked state (UseCustomImages must be true).
  • IndeterminateImageIndex - Index of the image to display when the node is in the Indeterminate state (UseCustomImages must be true).

The above four properties have all been placed in a single category in the property browser, named CheckState.

Class TriStateTreeNode

The class TriStateTreeNode has been derived from System.Windows.Forms.TreeNode, and exposes the extra functionality described below:

  • It hides the original Checked property, and returns true when its CheckState property is either Checked or Indeterminate. The property returns Unchecked when CheckState is Unchecked.
  • Additional read-only property CheckState which returns either Checked/Unchecked/Indeterminate depending on the current state.
  • Additional read-write property IsContainer which determines if a TreeNode behaves as a container or as an item.
  • Additional read-write property CheckboxVisible which determines if a node exposes a checkbox.
  • Internal property NodeLineType (see previous explanation).
  • Internal method SetCheckedState( CheckState value): Provides an interface for the TriStateTreeView class.

Sample code

C#
private void ConfigureTreeView()
{
    TriStateTreeNode folderNode = null;

    TriStateTreeNode rootNode = 
      new TriStateTreeNode( "Home - \"CheckboxVisible = false\"." );
    rootNode.CheckboxVisible = false;
    rootNode.IsContainer = true;

    for( int i = 1; i < 4; i++ )
    {
        folderNode = new TriStateTreeNode( string.Format( "Foldernode {0}," + 
                         " can show 3 states, as shown here.", i), 0, 1 );
        folderNode.IsContainer = true;
        rootNode.Nodes.Add( folderNode );
    }

    folderNode = new TriStateTreeNode("Foldernode 4, " + 
                     "cannot be checked, as shown here.", 0, 1);
    folderNode.IsContainer = true;
    folderNode.CheckboxVisible = false;

    rootNode.Nodes.Add(folderNode);

    TriStateTreeNode firstFolder = rootNode.FirstNode as TriStateTreeNode;
    for(int i = 1; i < 3; i++)
    {
        TriStateTreeNode itemNode = 
          new TriStateTreeNode( string.Format( "Item node {0}", i ), 2, 2 );
        firstFolder.Nodes.Add( itemNode );
    }

    TriStateTreeNode secondFolder = firstFolder.NextNode as TriStateTreeNode;
    for(int i = 1; i < 3; i++)
    {
        TriStateTreeNode itemNode = 
          new TriStateTreeNode( string.Format( "Item node {0}", i ), 2, 2);
        secondFolder.Nodes.Add( itemNode );
    }

    TriStateTreeNode thirdFolder = secondFolder.NextNode as TriStateTreeNode;
    for(int i = 1; i < 3; i++)
    {
        TriStateTreeNode itemNode = 
          new TriStateTreeNode( string.Format( "Item node {0}", i ), 2, 2 );
        thirdFolder.Nodes.Add( itemNode );
    }

    TriStateTreeNode fourthFolder = folderNode;
    fourthFolder.CheckboxVisible = false;
    for(int i = 1; i < 3; i++)
    {
        TriStateTreeNode itemNode = 
          new TriStateTreeNode( string.Format( 
          "Item node {0} - no checkboxes", i ), 2, 2 );
        itemNode.CheckboxVisible = false;
        fourthFolder.Nodes.Add( itemNode );
    }

    this.triStateTreeView1.SuspendLayout();
    this.triStateTreeView1.Nodes.Add( rootNode );
    this.triStateTreeView1.ResumeLayout();

    secondFolder.FirstNode.Checked = true;
    thirdFolder.Checked = true;
}

Points of interest

There are still a couple of issues I want to fix, feedback about it will be appreciated.

Microsoft has a TreeNodeCollectionEditor which will let you construct a tree at design time. Normally, I think this editor is not likely to be used since most treeviews will show dynamic data which will almost never be pre-configured. However... the editor doesn't work with this treeview because it adds TreeNodes instead of TriStateTreeNodes, which disables the entire tri-state concept. I haven't quite figured out what to do about it.

I guess a solution to this problem should involve hiding the Nodes property from the TreeView control by adding our own Nodes property which is a TreeNodeCollection like collection class that stores TriStateTreeNodes. That, together with a custom TreeNodeCollectionEditor, should just about take care of the problem.

History

  • 14 December 2007 - First version.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
Netherlands Netherlands
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionTri-State TreeView Control for .NET 1.1 Pin
Dionly24-Jun-13 4:54
Dionly24-Jun-13 4:54 
Questioncan't use control Pin
gladiator50200010-Feb-13 7:10
gladiator50200010-Feb-13 7:10 
Questionthanks your job and I chang some code to make it better Pin
tokenian24-Dec-12 21:15
tokenian24-Dec-12 21:15 
QuestionMissing Implementations for Nodes and Associated Methods Pin
Aylwyn26-Dec-11 14:43
Aylwyn26-Dec-11 14:43 
GeneralMy vote of 5 Pin
Member 369480730-Oct-11 22:42
Member 369480730-Oct-11 22:42 
QuestionUse WndProc() Hook to create "invisible" TreeNodes - How? Pin
Elitetum2-Aug-11 0:01
Elitetum2-Aug-11 0:01 
AnswerRe: Use WndProc() Hook to create "invisible" TreeNodes - How? Pin
Evert Timmer2-Aug-11 0:50
Evert Timmer2-Aug-11 0:50 
SuggestionHow to hide checkbox of the certain TreeNode in TreeView control Pin
Member 14778530-Jun-11 16:12
Member 14778530-Jun-11 16:12 
QuestionHow to change ForeColor property of extended treenode at runtime Pin
farhaan8-Aug-10 19:07
farhaan8-Aug-10 19:07 
How can i change ForeColor Property of Extended TreeNode at runtime?

When i try to do so, it sets the property but we are unable to see changes visually.

So please provide me some solution....
GeneralNode CheckState Pin
weepl40719-Nov-09 21:16
weepl40719-Nov-09 21:16 
GeneralTriStateTreeNode BackColor property Pin
Member 195776514-Nov-08 0:04
Member 195776514-Nov-08 0:04 
GeneralRe: TriStateTreeNode BackColor property Pin
Evert Timmer14-Nov-08 21:18
Evert Timmer14-Nov-08 21:18 
GeneralRe: TriStateTreeNode BackColor property Pin
geeklion30-Nov-11 21:23
geeklion30-Nov-11 21:23 
GeneralError. Node image is not refreshed when change state from code Pin
eyanson28-Oct-08 3:32
eyanson28-Oct-08 3:32 
GeneralRe: Error. Node image is not refreshed when change state from code Pin
Evert Timmer14-Nov-08 21:19
Evert Timmer14-Nov-08 21:19 
GeneralRe: Error. Node image is not refreshed when change state from code Pin
sdasdasdagg22-Jul-13 18:24
sdasdasdagg22-Jul-13 18:24 
QuestionQuestion on intermediate state Pin
nico.pyright29-Sep-08 11:32
nico.pyright29-Sep-08 11:32 
AnswerRe: Question on intermediate state Pin
ryanconrad9-Dec-08 2:32
ryanconrad9-Dec-08 2:32 
QuestionHow can I hide 2-nd icon i.e. folder_closed / folder_opened Pin
Zodzetrick27-May-08 2:39
Zodzetrick27-May-08 2:39 
AnswerRe: How can I hide 2-nd icon i.e. folder_closed / folder_opened Pin
Dorsch11-Oct-09 8:31
Dorsch11-Oct-09 8:31 
GeneralWorks for 2.0 as well!!!!!! Pin
Brad Bruce14-Dec-07 3:09
Brad Bruce14-Dec-07 3:09 
GeneralRe: Works for 2.0 as well!!!!!! Pin
Evert Timmer14-Dec-07 3:45
Evert Timmer14-Dec-07 3:45 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.