Click here to Skip to main content
Click here to Skip to main content

Tri-State TreeView Control for .NET 1.1

By , 14 Dec 2007
 

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
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

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)

About the Author

Evert Timmer
Software Developer (Senior)
Netherlands Netherlands
Member
No Biography provided

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
Hint: For improved responsiveness ensure Javascript is enabled and choose 'Normal' from the Layout dropdown and hit 'Update'.
You must Sign In to use this message board.
Search this forum  
    Spacing  Layout  Per page   
Questioncan't use controlmembergladiator50200010 Feb '13 - 7:10 
i add the dll and dragged the control .. it works like trivial one ..
,what am i missing ? and i am using .net 4 framework
Questionthanks your job and I chang some code to make it bettermembertokenian24 Dec '12 - 21:15 
QuestionMissing Implementations for Nodes and Associated MethodsmemberAylwyn26 Dec '11 - 14:43 
GeneralMy vote of 5memberMember 369480730 Oct '11 - 22:42 
QuestionUse WndProc() Hook to create "invisible" TreeNodes - How?memberElitetum2 Aug '11 - 0:01 
AnswerRe: Use WndProc() Hook to create "invisible" TreeNodes - How?memberEvert Timmer2 Aug '11 - 0:50 
SuggestionHow to hide checkbox of the certain TreeNode in TreeView controlmemberMember 14778530 Jun '11 - 16:12 
QuestionHow to change ForeColor property of extended treenode at runtimememberfarhaan8 Aug '10 - 19:07 
GeneralNode CheckStatememberweepl40719 Nov '09 - 21:16 
GeneralTriStateTreeNode BackColor propertymemberMember 195776514 Nov '08 - 0:04 
GeneralRe: TriStateTreeNode BackColor propertymemberEvert Timmer14 Nov '08 - 21:18 
GeneralRe: TriStateTreeNode BackColor propertymemberlijiuning30 Nov '11 - 21:23 
GeneralError. Node image is not refreshed when change state from codemembereyanson28 Oct '08 - 3:32 
GeneralRe: Error. Node image is not refreshed when change state from codememberEvert Timmer14 Nov '08 - 21:19 
QuestionQuestion on intermediate statemembernico.pyright29 Sep '08 - 11:32 
AnswerRe: Question on intermediate statemember-camalot-9 Dec '08 - 2:32 
QuestionHow can I hide 2-nd icon i.e. folder_closed / folder_openedmemberMarek Zgadzaj27 May '08 - 2:39 
AnswerRe: How can I hide 2-nd icon i.e. folder_closed / folder_openedmemberDorsch11 Oct '09 - 8:31 
GeneralWorks for 2.0 as well!!!!!!memberBrad Bruce14 Dec '07 - 3:09 
GeneralRe: Works for 2.0 as well!!!!!!memberEvert Timmer14 Dec '07 - 3:45 

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

Permalink | Advertise | Privacy | Mobile
Web03 | 2.6.130516.1 | Last Updated 14 Dec 2007
Article Copyright 2007 by Evert Timmer
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid