Click here to Skip to main content
13,446,762 members (39,541 online)
Click here to Skip to main content
Add your own
alternative version


6 bookmarked
Posted 20 Nov 2009

Wrapping a Treeview's Nodes Property to Provide Extra Functionality (Such as Sorting)

, 20 Nov 2009
Rate this:
Please Sign up or sign in to vote.
Workarounds for not being able to inherit from TreeViewCollection, and for having a read-only Nodes property


Have you ever wanted to sort a TreeView control by trying to inherit from TreeViewCollection (the data type of the Nodes property)? After writing an entire subclass doing just this, I tried to compile my work only to find out that there is a problem extending collections, see this MSDN post for more information.


So what now? The forum post offered little in the way of ideas. Without a way to extend the TreeViewCollection class, the next most logical choice is to put methods in either the TreeView subclass or in the callee class. Either way, you end up with a method signature that looks like this...

Add(TreeNodeCollection nodes, TreeNode node)

The first thing I didn't like was the two parameter method signature. If I had been able to extend the TreeViewCollection class (or was not sorting), I would only be passing the new TreeNode to the Add method (of the Nodes property).

The choice of putting a method like this in the callee class was the first option to go. I have multiple classes (forms classes in my) writing to the TreeView control. I also didn't like the choice of placing it in TreeView control, because essentially it's a static method (doesn't use any instance variables).

If there was only a way to add methods to the TreeViewCollection class... After thinking a while, I came up with an idea that is complete syntax candy to accessing the Nodes property directly. I was inspired by indexers to accomplish what I was looking for. For an introduction to Indexers, check out this tutorial.

Indexers are wonderfully flexible in C-Sharp. Typically, indexers are used to access a particular element of a collection or data set. My idea was to use an index to pass in an existing collection and place it in a wrapper class (the indexer's return type).

Using the Code

First I started by adding a property to my subclass of the TreeView control. The property was called SortedNodes and was of type InsertionSortWrapper. InsertionSortWrapper is basically the method I was planning to have in the subclass of TreeViewCollection (with override and virtual modifiers removed). Adding an indexer allowed convenient wrapping of any Nodes collection using the following syntax...

// This code compares traditional usage with wrapper usage
private void buttonPopulate_Click(object sender, EventArgs e)
    for (int i = 0; i < 100; i++)
        TreeNode topLevelNode = new TreeNode(RandomString());
        // Replacement for... sortedTreeView.Nodes.Add(topLevelNode);
        for (int j = 0; j < 20; j++)
            TreeNode childNode = new TreeNode(RandomString());
            // Replacement for... topLevelNode.Nodes.Add(childNode);

This code is made possible by using an indexer, passing the top level Nodes property to the constructor of InsertionSortWrapper, and making that your SortedNodes property in the TreeView. The code looks like this...

public sealed class InsertionSortWrapper
    public InsertionSortWrapper this[TreeNodeCollection collection]
            return new InsertionSortWrapper(collection);

    private TreeNodeCollection Nodes

    public InsertionSortWrapper(TreeNodeCollection actualNodes)
        Nodes = actualNodes;

    // Several Add() methods and compare functions (not shown here)

In the demo, I provided an insertion sort implementation. The wrapper provides Add() methods that have the same signature as in TreeViewCollection. The public methods in the wrapper use the private Nodes property to do all the real work on the actual nodes; finding the proper place to insert, and inserting the node there. You could implement additional methods or any sorting you choose. While you wouldn't have to use the same signatures as the methods in TreeViewCollection, it is the primary reason I had for implementing this. Here is the core of the insertion sort...

public int Add(TreeNode node, bool flagOnTop)
    // The flagOnTop parameter will insert the new TreeNode before
    // any other TreeNodes that do not have that flag set.
    if (flagOnTop)
        node.Tag = FLAG_ONTOP;
        node.Tag = FLAG_NONE;
    // Get Insertion Index
    int index = GetInsertionIndex(node);
    Nodes.Insert(index, node);
    return index;

private int GetInsertionIndex(TreeNode node)
    bool newNodeIsOnTop = ((((Int32)node.Tag) & FLAG_ONTOP) > 0);
    for (int i = 0; i < Nodes.Count; i++)
        TreeNodeCompareResult result =
            TreeNodeCompare(Nodes[i].Text, node.Text);
        bool testNodeIsOnTop = ((((Int32)Nodes[i].Tag) & FLAG_ONTOP) > 0);
        if (!newNodeIsOnTop && testNodeIsOnTop)
        if (newNodeIsOnTop && !testNodeIsOnTop)
            return i;
        if (result == TreeNodeCompareResult.LessThan) // <
        if (result != TreeNodeCompareResult.LessThan) // >=
            return i;
    return Nodes.Count;


  • 17 November 2009 - Original post


This article, along with any associated source code and files, is licensed under The Microsoft Public License (Ms-PL)


About the Author

Software Developer
United States United States
C++ programmer, 1994 to 2009

Java programmer, 2006 to 2008

C-Sharp programmer, 2007 to 2009

I am the owner, operator, lead programmer, and lead web developer of (2009) is a small software engineering company. Our first product, VKO, is a macro program with an embedded LUA scripting language.

You may also be interested in...

Comments and Discussions

Generalone question and a small suggestion [modified] Pin
BillWoodruff21-Nov-09 21:18
memberBillWoodruff21-Nov-09 21:18 
GeneralRe: one question and a small suggestion Pin
J.Guyette24-Nov-09 15:30
memberJ.Guyette24-Nov-09 15:30 
BillWoodruff wrote:
I think when you write "TreeViewCollection" what you really intend to say is "TreeNodeCollection."

Good catch, thanks! Next update I'll correct this. Smile | :)

BillWoodruff wrote:
Okay, I get this is an Index Property, but I am puzzled why, in such a property you would be returning a new Instance of TreeNodeCollection.

Actually, the indexer is returning a new instance of InsertionSortWrapper, which wraps any existing TreeNodeCollection instance (the Nodes properties). Once wrapped, the wrapper class's methods are used to manipulate the TreeNodeCollection instead. Smile | :)


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.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web04-2016 | 2.8.180314.2 | Last Updated 20 Nov 2009
Article Copyright 2009 by J.Guyette
Everything else Copyright © CodeProject, 1999-2018
Layout: fixed | fluid