Introduction
There are actually several reasons that made me start doing this:
- There are almost no tree control samples available out there. Nothing for VB.NET.
- There are almost no examples of rich time design support for collection of controls.
- I needed a tree with various image sizes (for a DVD collection).
- I hated to not be able to show PNG images correctly within a tree.
- I wanted to go deep into a control.
I'm not saying my article or my component is great work, but at least it'll give the newbie a rough start on that matter. Of course, I would say that my work is not free! I'd like to put it as ShareYourWorkWare ;) Meaning that if someone wants to improve it, he could make the others benefit as well.
Background
This article will reflect several bits of code that were put together in a kind of complete component. Among those you'll find:
- How to build a tree (a component that has a collection property that itself has collections, etc.)
- Implementing a real
CollectionBase
property.
- How to make a control "Design Time Enabled"
- Using
<Designer()>
.
- Inheriting from
ControlDesigner
.
- Twisting the
PropertyGrid
.
Collection
s
TypeConverter
s
PropertyDescriptor
- Implementing
ICustomTypeDescriptor
- And many more.
Re-usage
Mea culpa, I know... I've been reusing two nice piece of code that are available on the web. First of all, the great "Managed C++ Wrapper of UxTheme" from Don Kackman, and secondly, The "VisualStyles" provider from SkyBound.
The code itself
Let's try to start from somewhere.
As stated before, I wanted to write a tree control. Which is not an easy thing to do, especially if you have no clue on how to start. First, I'd thought about deriving from the original TreeView
control, but I soon realized that it was not possible for what I wanted.
In fact, I needed a tree control that is able to show images that are not always of the same size. Point was: creating a DVD collection application that shows all DVDs within a tree, showing a thumbnail image of the DVD cover. I also imagined a control that could have the famous Text
property as long as an "optional" description.
TreeList
This is the main component. It's derived from Control
. I've read somewhere on the web that the tree is supposed to take care of all the paintings. That's how I've implemented it. The main properties of TreeList
are:
Nodes
(represents a collection of TreeListNode
)
SelectedNode
(the node currently selected)
PointedNode
(the node currently pointed by the right mouse click).
I specified a Designer (shown below) in order to enable rich design time experience. This is how it is declared:
<Designer(GetType(TreeListDesigner))> _
Public Class TreeList Inherits Control
The Nodes
property needed to have some special definition as well to see it correctly in the PropertyGrid
:
Private WithEvents _Nodes As TreeListNodeCollection
<Category("Collection"), _
DesignerSerializationVisibility(DesignerSerializationVisibility.Content)> _
Public ReadOnly Property Nodes() As TreeListNodeCollection
Get
Return _Nodes
End Get
End Property
It's gotta be using the DesignerSerializationVisibility.Content
in order to be able to display it that way:
Notice that instead of having the traditional "(Collection)", I show the number of subnodes along with a nice (+) sign to expand it and show its internal properties.
TreeListNodeCollection
This holds a collection of TreeListNode
s (it's represented as the "Nodes
" property). That's its definition:
<TypeConverter(GetType(TreeListNodeCollectionConverter)), _
Editor(GetType(TreeListNodeCollectionEditor), GetType(UITypeEditor)), _
DesignTimeVisible(False), _
ToolboxItem(False), _
Serializable()> _
Public Class TreeListNodeCollection
Inherits CollectionBase
Implements ICustomTypeDescriptor
Notice here, the use of a TypeConverter
. (That allows to show "3 node(s)" instead of "(Collection)", the user of a customized Editor
avoids the problem when you have a collection of collection within a property.)
TreeListNode
This represents a node. It's inherited from Component
. That was the only way to achieve a correct designer for the TreeList
. It is defined that way:
<TypeConverter(GetType(TreeListNodeConverter)), _
DesignTimeVisible(False), _
ToolboxItem(False), _
Serializable()> _
Public Class TreeListNode
Inherits Component
It also has a property called "Nodes
" which represents a TreeListNodeCollection
(in order to hold its child nodes).
TreeListDesigner
This is the designer of the TreeList
component, it inherits from ControlDesigner
and allows the user to select a node at design time. It also helps when a node is selected to change the content of the PropertyGrid
displayed at design time.
TreeListNodeCollectionConverter & TreeListNodeConverter
Those are the converters for Collection and Node, it allows to change their respective visualizations on the PropertyGrid
object. For instance, a node showing its name instead of "TreeListNode1
".
TreeListNodeCollectionEditor
This is the collection editor stated above. Allows to use a CollectionEditor
from within another CollectionEditor
.
TreeListNodePropertyDescriptor
This is the piece that makes Nodes
have its little (+) sign at design time ;)
Points of Interest
I've learned a lot of things writing this component. I know that it is not really finished yet, but I hope that other people will join in to move forward and bring it to a stable state.
Progress
I also wanted to implement a possibility to show a tree being filled without having to wait for a non responsive control. Therefore the property "IsBusy()
" of the TreeList
can be set to show a progressbar.
VisualStyles
I've also put the option to draw the tree (kind of fantasy) without the Windows XP styles.
Scrollbars
I wanted to have scrollbars if the content of the control was too small to show everything. This was a bit of a question for me. I used the Skybound.VisualStylesProvider
to achieve the XP look.
Additional insight
I'll be writing more in-depth about this control later on if I see that people like it.
History
That was my first article guys, hope you enjoyed it ;)
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.