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

Advanced TreeView for .NET

By , 10 Jul 2006
 

TreeViewAdv in Multi-Column mode

Introduction

Working on several different projects, I was needed to display and edit hierarchical data. Of course, the first thing you will do is to use the standard .NET TreeView control. It works pretty well if you only need basic features. But learning this control to do something more complex is not an easy job. I could not find an alternative TreeView control which is free and fully meets my needs, so finally I decided to write my own.

The architecture of this control comes mainly from the Java Swing component, with some modifications. These are the key features of the TreeViewAdv control:

  • Model-View architecture - Will be covered in a separate section of this article.
  • Multiselection - Maybe the first limitation which you will find in the standard TreeView is that it’s not possible to select more then one node.
  • Unlimited number of controls for each node - You can display three icons + a CheckBox + two Labels.
  • Multicolumns - You can split the TreeView into several columns.
  • Load on Demand - Lazy load of child nodes.
  • Drag & Drop highlighting - Dynamically highlight the drop position.
  • 100% pure .NET code - No WinAPI is used in this control.

The following screenshots illustrate the TreeViewAdv features:

Drag&Drop highlighting

Multiselection

Using ComboBox to edit node

Model-View Architecture

I really like the Model-View pattern, and decided to use it in this control. The main idea of this pattern is to split the model (business object) from its visualization (control). If the model changes, it notifies the view by firing corresponding events. The view asks the model for details, if needed, and displays the changes. The model is described by ITreeModelInterface:

public interface ITreeModel
{
    IEnumerable GetChildren(TreePath treePath);
    bool IsLeaf(TreePath treePath);

    event EventHandler<TreeModelEventArgs> NodesChanged; 
    event EventHandler<TreeModelEventArgs> NodesInserted;
    event EventHandler<TreeModelEventArgs> NodesRemoved; 
    event EventHandler<TreePathEventArgs> StructureChanged;
}

It’s very simple, and you need to implement only two methods. GetChildren should return the list of child nodes of the specified parent (empty for root nodes). IsLeaf method tells TreeView whether it should try to read child nodes of the specified parent. If you wish TreeView to dynamically track model changes, you need to use one of several events of the ITreeModel interface. The most common is the StructureChanged event, which cause the TreeView to fully refresh the specified node (or empty, for the whole model). For example, see the default implementation of the ITreeModel interface – the TreeModel class.

To specify the exact node in the model, TreePath class is used. It stores the path from the root to the node, in the FullPath property.

public class TreePath
{
    public object[] FullPath{ get; }
    public object LastNode{ get; }
    public object FirstNode{ get; }
}

Using TreeView

In the source code, you can find two examples of how to use TreeViewAdv. The simplest way is to use TreeModel. All you need is to populate it with data and display it in the view:

_model = new TreeModel();
_model.Nodes.Add(new Node("Root"));
_tree.Model = _model;

The Node class, which is used in TreeModel, contains only the ‘Text’ and ‘IsChecked’ properties. If you need additional properties, you can create an ancestor of the Node class and use it in TreeModel.

But to use the full power of the TreeViewAdv, you should create your own realization of the ITreeModel interface. See the folder browser presented in the source code, for an example.

Customizing TreeView

There are a number of properties which help to customize the look and behavior of the TreeView. The main ones are:

  • Model - Assign your model to this property to display it.
  • NodeControls - The collection of controls which will be used to visualize the model. You should provide at least one NodeControl in order to see the model.
  • LoadOnDemand - Read all child nodes at start-up or when the parent node expands.
  • SelectionMode - Single (no multi-selection), Multi, MultiSameParent (children of only one node can be selected).
  • UseColumns - Display data in columns or not.
  • Columns - The collection of columns. For each column, you can specify its header, width and alignment.

NodeControls

The standard TreeView can display only one icon, CheckBox, and Label for each node. In TreeViewAdv, you can use any number of NodeControl. All controls must inherit from the ‘NodeControl’ abstract class. Inherited classes should contain the code to draw the control and the code to respond on user actions – mouse and keyboard events.

NodeControl

This is the class diagram of all NodeControls provided by the library:

Class diagram

The BindableControl class provides a ‘DataPropertyName’ which is used in the control to read and write data to the node. All that you need is to specify the name of the property of your class.

Terms and Conditions

The TreeViewAdv control is provided as free software with open source code. You can use it in your applications if the original copyright is kept.

The latest version of TreeViewAdv is always available here. Please feel free to add your comments and suggestions in the forum there.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

Andrey Gliznetsov
Software Developer
Russian Federation Russian Federation
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

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
QuestionHow to install the treeviewmemberMember 950484425-Apr-13 22:21 
Hi!
 
I feel like a total moron asking this, but how do I install and use the treeview in my projects? I am using Visual Studio 2012, winforms, C#.
AnswerRe: How to install the treeviewmemberCh4m3l30n17-Jun-13 13:30 
1. Right-click the Solution within the Solution Explorer (panel on top-right).
2. Select Add > Existing Project.
3. Browse to and Open the Aga.Controls.csproj file.
BugGetting Error while working in combo boxmembersuresh111019837-Apr-13 21:36 
I have added a combo box in tree view. while choose a item in combo box i am getting the following error.
 
"Attempted to read or write protected memory. This is often an indication that other memory is corrupt".
 
Can u able to fix it or tell me some work around . waiting for your response
 
Thanks in advance,
Suresh.
Question2 different label for one nodememberMember 986945021-Mar-13 22:51 
Hello,
How can i change the text of each label (for a same node) separatly?
 
For example i want to add a node with 2 label (tb1 and tb2)
       NodeTextBox tb1 = new NodeTextBox();
            tb1.DataPropertyName = "Text";
            treeViewAdv1.NodeControls.Add(tb1);
 
            NodeTextBox tb2 = new NodeTextBox();
            tb2.DataPropertyName = "Text2";
            treeViewAdv1.NodeControls.Add(tb2);
 
And i want the text to be like that : AAA BBBB
Please can you tell me how can i do that.
 
Thanks,
QuestionMove Up & down functionalitymemberRam Shelke16-Mar-13 23:23 
can we move the nodes as up and down?
 
if yes. please tell me how to do that D'Oh! | :doh:
AnswerRe: Move Up & down functionalitymemberWilliam Winner18-Mar-13 2:42 
You do that through .NET drag and drop. For an introduction, see here: Introduction to TreeView Drag and Drop (VB.NET)[^]
QuestionTreeview binding in databasememberMember 967163519-Dec-12 0:39 
hi,
 
am very new to Visual Studio 2008 C#. I would like to populate a Tree View with load data's from database at run time and when a specific Parent/child is clicked it will open a form assigned to that node/child details. Is there a sample code that I can look at that does this?
QuestionAdd Node after a nodememberPapyRef29-Nov-12 11:07 
I want to add node after a node on right button mouse click.
Is it possible ? How can I do that ?
 
        
private void treeViewCmd_NodeMouseClick(object sender, TreeNodeAdvMouseEventArgs e)
        {
            if (e.Button == MouseButtons.Right)
            {
// How can I a node after this node click ?
            }
        }
PapyRef, vous suggère de venir faire un tour sur SEO Black Inside (http://www.seoblack-inside.com/), vous ne serez pas déçu !

Suggestion[My vote of 2] Lack of examples...memberNiyazi Yarar23-Nov-12 12:25 
I'd like have a multi-column (5 column) treeviewlist, which should have 4 comboboxes for the last 4 columns.
 
I couldn't find any examples about usage of multi-column & node controls together, anywhere on the net, neither in this page as well.
 
Anyone could guide me?
The problem is not the problem. The problem is your attitude about the problem. Do you understand? `Jack Sparrow

GeneralMy vote of 5memberSimon_12-Nov-12 6:52 
Super ! Thank you
QuestionExpand NodememberKenneth Psaila5-Oct-12 1:45 
Is it possible to always expand the root node. When i am checking treeview.root.isexpanded the result is always true but the first node is never expanded.
QuestionShow/Hide TreeNodemembermccallug3-Oct-12 6:14 
Does anyone know a way to set the visibility of a tree node? I can't find a way to hide individual nodes or even remove them.
QuestionScrolling bugmemberare_all_nicks_taken_or_what18-Sep-12 5:07 
Run the Sample application. Select "Folder Browser".
 
1) Make sure the vertical scrollbar becomes visible.
2) Press END key.
3) Now hold down UP key.
 
The scrollbar flickers like a mad dog! Up and down, up and down...
NewsRe: Scrolling bugmemberNiyazi Yarar24-Sep-12 3:44 
LOL, I'd like to see that dog Smile | :)
mn.yarar

QuestionHangs in FindModel()memberare_all_nicks_taken_or_what18-Sep-12 4:56 
Excellent component! But... it took me five seconds to crash it Poke tongue | ;-P
 
When playing around with drag'n'drop I got stuck in the while-loop below (add a few nodes and drag quickly back and forth). The reason seems to be that both node and node.Parent equal this.
 
private TreeModel FindModel()
{
	Node node = this;
	while (node != null)
	{
		if (node.Model != null)
			return node.Model;
		node = node.Parent;
	}
	return null;
}

AnswerRe: Hangs in FindModel()memberare_all_nicks_taken_or_what18-Sep-12 5:03 
Possible fix:
 
private void _tree_DragDrop(object sender, DragEventArgs e)
{
	TreeNodeAdv[] nodes = (TreeNodeAdv[])e.Data.GetData(typeof(TreeNodeAdv[]));
	Node dropNode = _tree.DropPosition.Node.Tag as Node;
	if (_tree.DropPosition.Position == NodePosition.Inside)
	{
		foreach (TreeNodeAdv n in nodes)
		{
                    // (n.Tag as Node).Parent = dropNode;
                    // FIX :)
                    Node node = (n.Tag as Node);
                    if (dropNode != node)
                        node.Parent = dropNode;
		}
		_tree.DropPosition.Node.IsExpanded = true;
	}

QuestionCPOL license termsmemberBarbara Evans14-Aug-12 23:18 
Hi,
My Legal Department tell me I cannot use any code that is covered by the CPOL because of item 7.
Can we discuss whether you are willing to amend the terms and conditions, so that I can use your excellent software (WPF TreeListView Control)?
It would be a real shame if I have to look for an alternative, as there is nothing out there that comes close.
thanks
Barbara
QuestionRefreshing a node with out collapsing the treememberDavid Koenig12-Jul-12 20:12 
Hi,
 
great control, but one question:
i have implemented a model with 'GetChildren()' and 'IsLeaf()' and the treeview (with 'UseColumn=true') is working fine.
A backgroundworker that is implemented in the model will reload some data in the background by clicking on a refresh button or in a regular interval. After the reload of the data an event method which is implemented in the model will be raised.
Now i want to refresh the treeview out of this event method. How can i do this, without collapsing the nodes? When i use 'OnStructureChange()' the whole tree will be collapsed. The same with the 'Refresh()' method.
AnswerSet the Startup Project to SampleApp to avoid exception "Assembly doesn't contain any UserControl types."memberDavid Deley6-Jul-12 19:01 
Right-click on the Solution 'TreeViewAdv'
select Properties
 
(Solution 'TreeViewAdv' Property Pages)
(left side)
Common Properties > Startup Project
Single startup project
set that to "SampleApp" instead of "Aga.Controls"
 

(image)
http://www.daviddeley.com/misc/TreeViewAdv.gif[^]
 

(See end of)
http://www.c-sharpcorner.com/UploadFile/LivMic/Control_Combo_2005_109112006131010PM/Control_Combo_2005_1.aspx[^]
QuestionVertical Column HeadersmemberMatthysDT6-Jul-12 0:24 
Great article!
 
Any advice on how to get a treeListView like this one with vertical column headers?
 
Typically, we'll need this combination of features due to a large number of checkbox columns.
QuestionExport to CSV or Excelmemberksanghavi21-Jun-12 10:39 
hello,
 
I have used this control in my application now my client need to save all information in some CSV file. So is there any way we can traverse to all nodes in easy way like
foreach(Row row in treeView)
{
foreach(column in row)
{}
}
QuestionSynchronize scrolling?memberdenciaq31-May-12 20:57 
I have two trees placed side by side. I want to synchronize vertical and horizontal scrolling in both control so scrolling the first one will scroll the second tree.
Is there a simple way to do this?
Thanks in advance.
GeneralMy vote of 5memberkorolevsa14-Apr-12 3:26 
Good Control
QuestionTrouble DownloadingmemberJason Gauthier10-Apr-12 11:10 
In trying to download the zip file, I am presented with a blank page and nothing else. Has anybody experienced this? How can I get it fixed?
BugLosing reference to the TreeNodeAdv inside node controlsmemberMember 85781515-Apr-12 1:20 
This control has a very nasty feature.
 
When the TreeViewAdv call the ReadChilds() method, it clears the child nodes on the parent, and then recreates them using *new instances of TreeNodeAdv* (that's the problematic part), appending them as childs of the parent node.
 
When you are handling the updated value on an overriden DoApplyChanges() inside a EditableControl, it receives a TreeNodeAdv node as a parameter. Then you call SetLabel() to set the value to the underlying Node object. But when you update a property of the underlying Node object you normally call NotiyModel(). It ends calling ReadChilds() on the TreeViewAdv control.
 
So what happens? You're still inside the DoApplyChanges but the TreeNodeAdv node that you got as a parameter is no longer the TreeNodeAdv that is actually included in the TreeViewAdv, so you can't do anyting with it, reference it in any way (like setting it's Selected status, or whatever).

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

Permalink | Advertise | Privacy | Mobile
Web04 | 2.6.130619.1 | Last Updated 10 Jul 2006
Article Copyright 2006 by Andrey Gliznetsov
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid