IntegralUI TreeListView User Guide - Lidor Systems
IntegralUI TreeListView User Guide - Lidor Systems
IntegralUI TreeListView User Guide - Lidor Systems
Create successful ePaper yourself
Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.
<strong>User</strong> <strong>Guide</strong><br />
for <strong>IntegralUI</strong> <strong>TreeListView</strong> v3.2<br />
© 2011 <strong>Lidor</strong> <strong>Systems</strong>. All rights reserved
Table of contents<br />
Introduction 4<br />
Architecture 5<br />
Object Model 5<br />
Event Model 8<br />
Editor 9<br />
Appearance 13<br />
Working with styles 13<br />
How to change the appearance of control border 14<br />
Use of column’s individual styles 16<br />
Use of node’s individual styles 17<br />
Use of subitem’s individual styles 18<br />
How to create alternate look of nodes 20<br />
Style serialization and reuse 22<br />
Visual Styles 22<br />
Themes 22<br />
Behavior 23<br />
Working with Columns 23<br />
Add/Remove operations 23<br />
How to add existing column collection 24<br />
How to fix column to the left or right side of the control 24<br />
How to fix the column width 25<br />
Different types of column content 25<br />
How to show custom images in column 28<br />
How to show custom control in column 31<br />
How to show custom objects in column 34<br />
Working with Nodes 38<br />
Add/Remove operations 38<br />
How to add existing node collection to the <strong>TreeListView</strong> 39<br />
How to edit the node text 39<br />
Checked nodes 41<br />
How to preserve checked nodes 42<br />
Selected nodes 43<br />
Multiple selection 43<br />
Hover selection 43<br />
How to preserve selection 43<br />
Working with Subitems 44<br />
Add/Remove operations 44<br />
2
Standard selection 45<br />
Frame selection 45<br />
Drag&Drop operations 45<br />
Use of permissions 46<br />
How to create a custom drag&drop operation 46<br />
How to perform drag&drop for collection of nodes 50<br />
How to perform drag&drop of an node content to other controls 54<br />
Sorting 55<br />
Use of predefined sorting method 55<br />
Create custom sorting 58<br />
Search 62<br />
How to find an node by using specific criteria 62<br />
How to get an node reference from mouse position 62<br />
Keyword search 63<br />
How to maintain scroll position 66<br />
XML Encoding 68<br />
XML Tags that are supported 68<br />
Working with containers: and tags 70<br />
Working with tag 74<br />
Working with font style tags 75<br />
Working with tag 76<br />
Working with tag 77<br />
Working with tag 78<br />
Working with , and tags 79<br />
Working with tag 84<br />
Using word wrap 86<br />
Serialization 87<br />
How to serialize the control content in Streams 87<br />
How to serialize the control content in files 88<br />
How to serialize the control content SQL database 90<br />
Sample projects 92<br />
3
Introduction<br />
This guide will provide you with information on how to work with <strong>IntegralUI</strong> <strong>TreeListView</strong> control<br />
and help you to successfully include it in your applications.<br />
With <strong>IntegralUI</strong> <strong>TreeListView</strong> you can present your data in very customizable way. This control<br />
takes the best from TreeView and ListView controls and much more. It allows you to create rich<br />
hierarchical structure of your data.<br />
Here are some of the main features:<br />
• Highly customizable appearance<br />
• Rich content: Text, Images, Hyperlinks, Controls, CheckBox, Flags; can be included in<br />
every column, node or subitem<br />
• Arrange column content in custom layouts<br />
• Arrange node content in custom layouts<br />
• Advanced Drag&Drop operations<br />
• Built-in sorting and option to add custom sort operations<br />
• Fast loading along with custom progress presentation<br />
• XML encoding & serialization<br />
• Theme support<br />
4
Architecture<br />
<strong>IntegralUI</strong> <strong>TreeListView</strong> control is part of <strong>IntegralUI</strong> family of products, and as such uses common<br />
infrastructure shared among other controls. The <strong>TreeListView</strong> class is inherited from ListBase class<br />
which is a parent class for all list controls in <strong>IntegralUI</strong> class library. Because of this, you will find<br />
many similarities between other controls like ListBox, ListView and <strong>TreeListView</strong>, which all belongs<br />
to the <strong>IntegralUI</strong> Lists class library.<br />
Object model<br />
To fill the <strong>TreeListView</strong> control with data you need to use <strong>TreeListView</strong>NodeCollection which holds<br />
a collection of nodes. Every node can contain standard objects like StateImage, CheckBox, Icon,<br />
Text arranged in single line. Furthermore if you want to present your data in multiple columns,<br />
every node contain a collection of SubItems. There is direct relation between columns and<br />
subitems. Meaning, if you reorder columns, the subitems for each node will also be reordered.<br />
Additionally, each column, node and subitem can contain custom content in their space. By<br />
default a plain text is used to present data in these objects. However, by using XML tags you can<br />
create custom layouts for each column, node or subitem. You can insert almost any custom<br />
objects like: Text, Images, Hyperlinks, Controls, CheckBox, Icons, Animated gifs etc. and arrange<br />
them in custom layouts by using Tables and paragraphs.<br />
The following pictures show you the difference between standard presentation, using just plain<br />
text and icons, and advanced presentation: using XML encoding in creation of custom objects.<br />
5
Normal mode<br />
Using XML Encoding<br />
6
In order to create custom look you can use many color and format styles for <strong>TreeListView</strong> control<br />
and for every column, node and subitem individually. Additionally, in further customization the<br />
styles can be changed for every part of the column, node or subitem content by using special XML<br />
tags.<br />
7
Event model<br />
There are many events which can help you to determine the current state of <strong>TreeListView</strong> control.<br />
Here is a complete list of events:<br />
• AfterCheck Occurs after the node's check box is checked<br />
• AfterCollapse Occurs after the node is collapsed<br />
• AfterExpand Occurs after the node is expanded<br />
• AfterLabelEdit Occurs after the node text is edited<br />
• AfterSelect Occurs after the node is selected<br />
• AfterSubItemSelect Occurs after the subitem is selected<br />
• BeforeCheck Occurs before the node's check box is checked<br />
• BeforeCollapse Occurs before the node is collapsed<br />
• BeforeExpand Occurs before the node is expanded<br />
• BeforeLabelEdit Occurs before the node text is edited<br />
• BeforeSelect Occurs before the node is selected<br />
• BeforeSubItemSelect Occurs before the subitem is selected<br />
• ColumnAdded Occurs after new column is added<br />
• ColumnAdding Occurs before new column is added<br />
• ColumnRemoved Occurs after column is removed from collection<br />
• ColumnRemoving Occurs before column is removed from collection<br />
• FocusedNodeChanged Occurs after the focused node is changed<br />
• FocusedNodeChanging Occurs before the focused node is changed<br />
• NodeAdded Occurs after new node is added<br />
• NodeAdding Occurs before new node is added<br />
• ItemDrag Occurs when the user begins dragging an node<br />
• ItemMouseHover Occurs when the mouse cursor hovers for some time over<br />
an node space<br />
• ItemObjectClicked Occurs after the user clicks an custom object (placed with<br />
XML encoding) in the control space<br />
• ItemObjectClicking Occurs before the user clicks an custom object (placed with<br />
XML encoding) in the control space<br />
• NodeRemoved Occurs after node is removed from collection<br />
• NodeRemoving Occurs before node is removed from collection<br />
• ScrollPosChanged Occurs when position of scrollbar has changed<br />
• SelectionModeChanged Occurs when selection type changes<br />
• SubItemSelectionChanged Occurs when selection of subitems is changed<br />
8
Editor<br />
There are two ways to create objects in <strong>TreeListView</strong> control: during design-time or<br />
programmatically.<br />
In design-time you can use the <strong>TreeListView</strong> Editor by right-clicking on the <strong>TreeListView</strong> control.<br />
The form will appear in which you can add, remove, change the columns, nodes or subitems.<br />
In order to create columns, nodes and subitems programmatically, you can use the following<br />
code:<br />
[VB]<br />
' Assuming that <strong>TreeListView</strong> control exist<br />
Private Sub InitList()<br />
' Suspend the layout logic for the <strong>TreeListView</strong> control<br />
Me.<strong>TreeListView</strong>1.SuspendUpdate()<br />
' Create three columns with header and footer description<br />
Dim column As <strong>TreeListView</strong>Column = Nothing<br />
For j As Integer = 0 To 2<br />
column = New <strong>TreeListView</strong>Column("Header " & j.ToString(), "Footer " &<br />
j.ToString())<br />
Me.treeListView1.Columns.Add(column)<br />
Next<br />
' Create root nodes<br />
Dim node As <strong>TreeListView</strong>Node = Nothing<br />
For i As Integer = 0 To 4<br />
9
node = New <strong>TreeListView</strong>Node("Node " & i.ToString())<br />
' Create subitems for this node<br />
CreateSubItems(node, i.ToString())<br />
' Create child nodes for this node<br />
CreateSubNodes(node, 0, i.ToString())<br />
Me.treeListView1.Nodes.Add(node)<br />
Next<br />
' Resume the layout logic for the <strong>TreeListView</strong> control<br />
Me.<strong>TreeListView</strong>1.ResumeUpdate()<br />
End Sub<br />
Private Sub CreateSubItems(ByVal parentNode As <strong>TreeListView</strong>Node, ByVal sufix As<br />
String)<br />
' Create subitems for specified node<br />
Dim subItem As <strong>TreeListView</strong>SubItem = Nothing<br />
For j As Integer = 0 To Me.treeListView1.Columns.Count - 1<br />
subItem = New <strong>TreeListView</strong>SubItem(("Item " & sufix) + j.ToString())<br />
parentNode.SubItems.Add(subItem)<br />
Next<br />
End Sub<br />
Private Sub CreateSubNodes(ByVal parentNode As <strong>TreeListView</strong>Node, ByVal level As<br />
Integer, ByVal sufix As String)<br />
' In this example only two levels in hierarchy are allowed<br />
If level = 2 Then<br />
Exit Sub<br />
Else<br />
' Create child nodes for specified node<br />
Dim node As <strong>TreeListView</strong>Node = Nothing<br />
For i As Integer = 0 To 1<br />
node = New <strong>TreeListView</strong>Node(("Node " & sufix) + i.ToString())<br />
' Create subitems for this node<br />
CreateSubItems(node, sufix + i.ToString())<br />
' Create child nodes for this node<br />
CreateSubNodes(node, level + 1, sufix + i.ToString())<br />
parentNode.Nodes.Add(node)<br />
Next<br />
End If<br />
End Sub<br />
[C#]<br />
using <strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Lists;<br />
. . .<br />
// Assuming that <strong>TreeListView</strong> control exist<br />
private void InitList()<br />
{<br />
// Suspend the layout logic for the <strong>TreeListView</strong> control<br />
this.treeListView1.SuspendUpdate();<br />
10
Create three columns with header and footer description<br />
<strong>TreeListView</strong>Column column = null;<br />
for (int j = 0; j < 3; j++)<br />
{<br />
column = new <strong>TreeListView</strong>Column("Header " + j.ToString(), "Footer " +<br />
j.ToString());<br />
this.treeListView1.Columns.Add(column);<br />
}<br />
}<br />
// Create root nodes<br />
<strong>TreeListView</strong>Node node = null;<br />
for (int i = 0; i < 5; i++)<br />
{<br />
node = new <strong>TreeListView</strong>Node("Node " + i.ToString());<br />
}<br />
// Create subitems for this node<br />
CreateSubItems(node, i.ToString());<br />
// Create child nodes for this node<br />
CreateSubNodes(node, 0, i.ToString());<br />
this.treeListView1.Nodes.Add(node);<br />
// Resume the layout logic for the <strong>TreeListView</strong> control<br />
this.treeListView1.ResumeUpdate();<br />
private void CreateSubItems(<strong>TreeListView</strong>Node parentNode, string sufix)<br />
{<br />
// Create subitems for specified node<br />
<strong>TreeListView</strong>SubItem subItem = null;<br />
for (int j = 0; j < this.treeListView1.Columns.Count; j++)<br />
{<br />
subItem = new <strong>TreeListView</strong>SubItem("Item " + sufix + j.ToString());<br />
}<br />
}<br />
parentNode.SubItems.Add(subItem);<br />
private void CreateSubNodes(<strong>TreeListView</strong>Node parentNode, int level, string sufix)<br />
{<br />
// In this example only two levels in hierarchy are allowed<br />
if (level == 2)<br />
return;<br />
else<br />
{<br />
// Create child nodes for specified node<br />
<strong>TreeListView</strong>Node node = null;<br />
for (int i = 0; i < 2; i++)<br />
{<br />
node = new <strong>TreeListView</strong>Node("Node " + sufix + i.ToString());<br />
// Create subitems for this node<br />
CreateSubItems(node, sufix + i.ToString());<br />
// Create child nodes for this node<br />
CreateSubNodes(node, level+1, sufix + i.ToString());<br />
11
}<br />
}<br />
}<br />
parentNode.Nodes.Add(node);<br />
12
Appearance<br />
Working with styles<br />
The <strong>IntegralUI</strong> <strong>TreeListView</strong> is very customizable control. You can customize every part of the<br />
control, starting from the background, border, columns, nodes, subitems etc. This is done by<br />
numerous styles with which you can set colors, fonts, alignment, rendering mode. Here is the list<br />
of general color and format styles:<br />
• CheckBoxStyle - The drawing style of the node’s check box<br />
• ColorStyle - The drawing style of the control<br />
• ExpandBoxStyle - The drawing style of the node expand/collapse button<br />
• FormatStyle - The format style of the control<br />
• ScrollBarStyle - The drawing style of horizontal and vertical scrollbar<br />
• ToolTipStyle - The drawing style of node’s tooltip<br />
There are general styles with which you can control the appearance for all columns, nodes and<br />
subitems.<br />
The list of column styles:<br />
• HoverColumnStyle - The drawing style of column when mouse hovers over it<br />
• ColumnFormatStyle - Style by which the column content is formatted<br />
• NormalColumnStyle - The default drawing style of the column<br />
• SelectedColumnStyle - The drawing style of column when it’s selected<br />
The list of node styles:<br />
• DisabledNodeStyle - The drawing style of node when it’s disabled<br />
• FocusedNodeStyle - The drawing style of node with input focus<br />
• HoverNodeStyle - The drawing style of node when mouse hovers over it<br />
• NodeFormatStyle - Style by which the node content is formatted<br />
• NormalNodeStyle - The default drawing style of the node<br />
• SelectedNodeStyle - The drawing style of node when it’s selected<br />
The list of subitem styles:<br />
• DisabledSubItemStyle - The drawing style of subitem when it’s disabled<br />
• HoverSubItemStyle - The drawing style of subitem when mouse hovers over it<br />
• SubItemFormatStyle - Style by which the subitem content is formatted<br />
• NormalSubItemStyle - The default drawing style of the subitem<br />
• SelectedSubItemStyle - The drawing style of subitem when it’s selected<br />
Furthermore, every column, node and subitem have their own set of the above styles with witch<br />
you can customize their appearance individually. These styles are:<br />
The list of individual column styles:<br />
• HoverStyle - The drawing style of column when mouse hovers over it<br />
• FormatStyle - Style by which the column content is formatted<br />
• NormalStyle - The default drawing style of the column<br />
• SelectedStyle - The drawing style of column when it’s selected<br />
The list of individual node styles:<br />
• DisabledStyle - The drawing style of node when it’s disabled<br />
• FocusedStyle - The drawing style of node with input focus<br />
• HoverStyle - The drawing style of node when mouse hovers over it<br />
• FormatStyle - Style by which the node content is formatted<br />
13
• NormalStyle - The default drawing style of the node<br />
• SelectedStyle - The drawing style of node when it’s selected<br />
The list of individual subitem styles:<br />
• DisabledStyle - The drawing style of subitem when it’s disabled<br />
• HoverStyle - The drawing style of subitem when mouse hovers over it<br />
• FormatStyle - Style by which the subitem content is formatted<br />
• NormalStyle - The default drawing style of the subitem<br />
• SelectedStyle - The drawing style of subitem when it’s selected<br />
How to change the appearance of control border<br />
In some cases you may want to change the border of the <strong>TreeListView</strong> to appear differently then<br />
the standard rectangular form. To achieve this goal several properties of the control FormatStyle<br />
needs to be changed. Here is a list of properties which controls a different part of the border:<br />
BorderCornerRadius – holds the value by which the border corner is rounded<br />
BorderCornerShape – responsible for changing the shape of every border corner<br />
BorderLineStyle – determines the thickness of border line<br />
BorderVisibility – determines which side of the border is visible<br />
These properties also exist in format style of every node.<br />
Here is an example where you can see how border can be customized:<br />
[VB]<br />
Imports <strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Style<br />
. . .<br />
' Changing the border of the <strong>TreeListView</strong> control<br />
Me.treeListView1.FormatStyle.BorderCornerRadius = 15<br />
Me.treeListView1.FormatStyle.BorderCornerShape.BottomLeft = CornerShape.Squared<br />
Me.treeListView1.FormatStyle.BorderCornerShape.BottomRight =<br />
CornerShape.Chamfered<br />
Me.treeListView1.FormatStyle.BorderCornerShape.TopRight = CornerShape.Squared<br />
Me.treeListView1.FormatStyle.BorderLineStyle = LineStyle.[Double]<br />
' Changing the border of the columns<br />
Me.treeListView1.ColumnFormatStyle.BorderCornerRadius = 7<br />
Me.treeListView1.ColumnFormatStyle.HeaderBorderCornerShape.BottomLeft =<br />
CornerShape.Squared<br />
Me.treeListView1.ColumnFormatStyle.HeaderBorderCornerShape.BottomRight =<br />
CornerShape.Chamfered<br />
Me.treeListView1.ColumnFormatStyle.HeaderBorderCornerShape.TopRight =<br />
CornerShape.Squared<br />
Me.treeListView1.ColumnFormatStyle.HeaderPadding = New Padding(3, 2, 3, 2)<br />
Me.treeListView1.ColumnFormatStyle.FooterBorderCornerShape.BottomLeft =<br />
CornerShape.Squared<br />
Me.treeListView1.ColumnFormatStyle.FooterBorderCornerShape.BottomRight =<br />
CornerShape.Chamfered<br />
Me.treeListView1.ColumnFormatStyle.FooterBorderCornerShape.TopRight =<br />
CornerShape.Squared<br />
Me.treeListView1.ColumnFormatStyle.FooterPadding = New Padding(3, 2, 3, 2)<br />
' Changing the border of the nodes<br />
Me.treeListView1.NodeFormatStyle.BorderCornerRadius = 7<br />
14
Me.treeListView1.NodeFormatStyle.BorderCornerShape.BottomLeft =<br />
CornerShape.Squared<br />
Me.treeListView1.NodeFormatStyle.BorderCornerShape.BottomRight =<br />
CornerShape.Chamfered<br />
Me.treeListView1.NodeFormatStyle.BorderCornerShape.TopRight = CornerShape.Squared<br />
Me.treeListView1.NodeFormatStyle.Padding = New Padding(3, 2, 3, 2)<br />
[C#]<br />
using <strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Style;<br />
. . .<br />
// Changing the border of the <strong>TreeListView</strong> control<br />
this.treeListView1.FormatStyle.BorderCornerRadius = 15;<br />
this.treeListView1.FormatStyle.BorderCornerShape.BottomLeft =<br />
CornerShape.Squared;<br />
this.treeListView1.FormatStyle.BorderCornerShape.BottomRight =<br />
CornerShape.Chamfered;<br />
this.treeListView1.FormatStyle.BorderCornerShape.TopRight = CornerShape.Squared;<br />
this.treeListView1.FormatStyle.BorderLineStyle = LineStyle.Double;<br />
// Changing the border of the columns<br />
this.treeListView1.ColumnFormatStyle.BorderCornerRadius = 7;<br />
this.treeListView1.ColumnFormatStyle.HeaderBorderCornerShape.BottomLeft =<br />
CornerShape.Squared;<br />
this.treeListView1.ColumnFormatStyle.HeaderBorderCornerShape.BottomRight =<br />
CornerShape.Chamfered;<br />
this.treeListView1.ColumnFormatStyle.HeaderBorderCornerShape.TopRight =<br />
CornerShape.Squared;<br />
this.treeListView1.ColumnFormatStyle.HeaderPadding = new Padding(3,<br />
2, 3, 2);<br />
this.treeListView1.ColumnFormatStyle.FooterBorderCornerShape.BottomLeft =<br />
CornerShape.Squared;<br />
this.treeListView1.ColumnFormatStyle.FooterBorderCornerShape.BottomRight =<br />
CornerShape.Chamfered;<br />
this.treeListView1.ColumnFormatStyle.FooterBorderCornerShape.TopRight =<br />
CornerShape.Squared;<br />
this.treeListView1.ColumnFormatStyle.FooterPadding = new Padding(3, 2, 3, 2);<br />
// Changing the border of the nodes<br />
this.treeListView1.NodeFormatStyle.BorderCornerRadius = 7;<br />
this.treeListView1.NodeFormatStyle.BorderCornerShape.BottomLeft =<br />
CornerShape.Squared;<br />
this.treeListView1.NodeFormatStyle.BorderCornerShape.BottomRight =<br />
CornerShape.Chamfered;<br />
this.treeListView1.NodeFormatStyle.BorderCornerShape.TopRight =<br />
CornerShape.Squared;<br />
this.treeListView1.NodeFormatStyle.Padding = new Padding(3, 2, 3, 2);<br />
15
The border for every subitem can also be changed. For this purpose you need to use the<br />
SubItemFormStyle.<br />
Use of column’s individual styles<br />
By default the appearance of columns is controlled by set of styles from their parent <strong>TreeListView</strong><br />
control.<br />
If you want to have separate look for a specific column, you can customize it from their individual<br />
styles. Before changing any of these styles, the StyleFromParent property for this columnmust be<br />
set to False. In the following example we will change the look of the column in its normal and<br />
hovered state:<br />
[VB]<br />
' Set the StyleFromParent to False, so that<br />
' a specific style changes be applied<br />
column.StyleFromParent = False<br />
' Change the look of the column, when it is in normal state<br />
column.NormalStyle.BackColor = Color.FromArgb(248, 250, 252)<br />
column.NormalStyle.HeaderColor = Color.LightSteelBlue<br />
column.NormalStyle.HeaderBorderColor = Color.LightSteelBlue<br />
' Change the look of the column, when it is in hovered state<br />
column.HoverStyle.BackColor = Color.FromArgb(255, 251, 244)<br />
column.HoverStyle.HeaderColor = Color.DarkOrange<br />
column.HoverStyle.HeaderBorderColor = Color.FromArgb(255, 192, 128)<br />
' Repaing the control<br />
Me.treeListView1.Invalidate()<br />
[C#]<br />
// Set the StyleFromParent to False, so that<br />
// a specific style changes be applied<br />
column.StyleFromParent = false;<br />
// Change the look of the column, when it is in normal state<br />
column.NormalStyle.BackColor = Color.FromArgb(248, 250, 252);<br />
column.NormalStyle.HeaderColor = Color.LightSteelBlue;<br />
column.NormalStyle.HeaderBorderColor = Color.LightSteelBlue;<br />
16
Change the look of the column, when it is in hovered state<br />
column.HoverStyle.BackColor = Color.FromArgb(255, 251, 244);<br />
column.HoverStyle.HeaderColor = Color.DarkOrange;<br />
column.HoverStyle.HeaderBorderColor = Color.FromArgb(255, 192, 128);<br />
// Repaing the control<br />
this.treeListView1.Invalidate();<br />
In the code above the node is the third node in the collection. Here is the result:<br />
Changes in normal state Changes in hover state<br />
Use of node’s individual styles<br />
By default the appearance of nodes is controlled by set of styles from their parent <strong>TreeListView</strong><br />
control.<br />
If you want to have separate look for a specific node, you can customize it from their individual<br />
styles. Before changing any of these styles, the StyleFromParent property for this node must be<br />
set to False. In the following example we will change the look of the node in its normal and<br />
hovered state:<br />
[VB]<br />
' Set the StyleFromParent to False, so that<br />
' a specific style changes be applied<br />
node.StyleFromParent = False<br />
' Change the look of the node, when it is in normal state<br />
node.NormalStyle.BackColor = Color.LightGreen<br />
node.NormalStyle.BorderColor = Color.LimeGreen<br />
' Change the look of the node, when it is in hovered state<br />
node.HoverStyle.BackColor = Color.LightSalmon<br />
node.HoverStyle.BorderColor = Color.Salmon<br />
node.HoverStyle.FillStyle = FillStyle.Vertical<br />
' Repaing the control<br />
Me.treeListView1.Invalidate()<br />
17
[C#]<br />
// Set the StyleFromParent to False, so that<br />
// a specific style changes be applied<br />
node.StyleFromParent = false;<br />
// Change the look of the node, when it is in normal state<br />
node.NormalStyle.BackColor = Color.LightGreen;<br />
node.NormalStyle.BorderColor = Color.LimeGreen;<br />
// Change the look of the node, when it is in hovered state<br />
node.HoverStyle.BackColor = Color.LightSalmon;<br />
node.HoverStyle.BorderColor = Color.Salmon;<br />
node.HoverStyle.FillStyle = FillStyle.Vertical;<br />
// Repaing the control<br />
this.treeListView1.Invalidate();<br />
In the code above the node is the third node in the collection. Here is the result:<br />
Changes in normal state Changes in hover state<br />
Use of subitem’s individual styles<br />
By default subitems doesn’t have color settings, except for the text color. In general the<br />
appearance of subitem is controlled by set of styles from their parent <strong>TreeListView</strong> control.<br />
If you want to have separate look for a specific subitem, you can customize it from their individual<br />
styles. Before changing any of these styles, the StyleFromParent property for this node must be<br />
set to False. In the following example we will change the look of the node in its normal and<br />
hovered state:<br />
[VB]<br />
' To avoid confusion between use of styles for node and subitem,<br />
' set parent node's hover style with transparent colors<br />
Me.treeListView1.HoverNodeStyle.BackColor = Color.Transparent<br />
Me.treeListView1.HoverNodeStyle.BorderColor = Color.Transparent<br />
' Set the StyleFromParent to False, so that<br />
' a specific style changes be applied<br />
subItem.StyleFromParent = False<br />
18
' Change the look of the nosubItemde, when it is in normal state<br />
subItem.NormalStyle.BackColor = Color.LightGreen<br />
subItem.NormalStyle.BorderColor = Color.LimeGreen<br />
' Change the look of the nosubItemde, when it is in hovered state<br />
subItem.HoverStyle.BackColor = Color.LightSalmon<br />
subItem.HoverStyle.BorderColor = Color.Salmon<br />
subItem.HoverStyle.FillStyle = FillStyle.Vertical<br />
' Repaing the control<br />
Me.treeListView1.Invalidate()<br />
[C#]<br />
// To avoid confusion between use of styles for node and subitem,<br />
// set parent node's hover style with transparent colors<br />
this.treeListView1.HoverNodeStyle.BackColor = Color.Transparent;<br />
this.treeListView1.HoverNodeStyle.BorderColor = Color.Transparent;<br />
// Set the StyleFromParent to False, so that<br />
// a specific style changes be applied<br />
subItem.StyleFromParent = false;<br />
// Change the look of the nosubItemde, when it is in normal state<br />
subItem.NormalStyle.BackColor = Color.LightGreen;<br />
subItem.NormalStyle.BorderColor = Color.LimeGreen;<br />
// Change the look of the nosubItemde, when it is in hovered state<br />
subItem.HoverStyle.BackColor = Color.LightSalmon;<br />
subItem.HoverStyle.BorderColor = Color.Salmon;<br />
subItem.HoverStyle.FillStyle = FillStyle.Vertical;<br />
// Repaing the control<br />
this.treeListView1.Invalidate();<br />
In the code above the node is the third node in the collection. Here is the result:<br />
Changes in normal state Changes in hover state<br />
19
How to create alternate look of nodes<br />
You can create standalone styles which in appropriate conditions can be applied to specific nodes.<br />
For example, every node with an even index can have one appearance and every node with odd<br />
index can have another appearance. But instead of changing the colors for every node, you need<br />
only to create two color styles, one style for the even rows and other for the odd rows.<br />
Here is a sample code that creates node list with alternate look:<br />
[VB]<br />
Imports <strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Lists<br />
Imports <strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Lists.Style<br />
. . .<br />
Private Sub ApplyAlternateLook()<br />
' Create the even color style<br />
Dim evenNodeStyle As New ListItemColorStyle()<br />
evenNodeStyle.BackColor = Color.WhiteSmoke<br />
evenNodeStyle.FillStyle = FillStyle.Horizontal<br />
' Create the odd color style<br />
Dim oddNodeStyle As New ListItemColorStyle()<br />
oddNodeStyle.BackColor = Color.Gainsboro<br />
oddNodeStyle.FillStyle = FillStyle.Horizontal<br />
' Cycle through all nodes and apply style changes<br />
For Each node As <strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Lists.<strong>TreeListView</strong>Node In<br />
Me.treeListView1.FlatNodes<br />
CreateSubItems(node, node.FlatIndex.ToString())<br />
' When you use individual styles for an node<br />
' the StyleFromParent needs to be set to False<br />
node.StyleFromParent = False<br />
If node.FlatIndex Mod 2 = 0 Then<br />
node.NormalStyle = evenNodeStyle<br />
Else<br />
node.NormalStyle = oddNodeStyle<br />
End If<br />
Next<br />
' Update the control<br />
Me.treeListView1.UpdateLayout()<br />
End Sub<br />
Private Sub CreateSubItems(ByVal parentNode As <strong>TreeListView</strong>Node, ByVal sufix As<br />
String)<br />
' Create subitems for specified node<br />
Dim subItem As <strong>TreeListView</strong>SubItem = Nothing<br />
For j As Integer = 0 To Me.treeListView1.Columns.Count - 1<br />
subItem = New <strong>TreeListView</strong>SubItem(("Item " & sufix) + j.ToString())<br />
parentNode.SubItems.Add(subItem)<br />
Next<br />
End Sub<br />
[C#]<br />
using <strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Lists;<br />
20
using <strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Lists.Style;<br />
. . .<br />
private void ApplyAlternateLook()<br />
{<br />
// Create the even color style<br />
ListItemColorStyle evenNodeStyle = new ListItemColorStyle();<br />
evenNodeStyle.BackColor = Color.WhiteSmoke;<br />
evenNodeStyle.FillStyle = FillStyle.Horizontal;<br />
// Create the odd color style<br />
ListItemColorStyle oddNodeStyle = new ListItemColorStyle();<br />
oddNodeStyle.BackColor = Color.Gainsboro;<br />
oddNodeStyle.FillStyle = FillStyle.Horizontal;<br />
// Cycle through all nodes and apply style changes<br />
foreach (<strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Lists.<strong>TreeListView</strong>Node node in<br />
this.treeListView1.FlatNodes)<br />
{<br />
CreateSubItems(node, node.FlatIndex.ToString());<br />
}<br />
}<br />
// When you use individual styles for an node<br />
// the StyleFromParent needs to be set to False<br />
node.StyleFromParent = false;<br />
if (node.FlatIndex % 2 == 0)<br />
node.NormalStyle = evenNodeStyle;<br />
else<br />
node.NormalStyle = oddNodeStyle;<br />
// Update the control<br />
this.treeListView1.UpdateLayout();<br />
private void CreateSubItems(<strong>TreeListView</strong>Node parentNode, string sufix)<br />
{<br />
// Create subitems for specified node<br />
<strong>TreeListView</strong>SubItem subItem = null;<br />
for (int j = 0; j < this.treeListView1.Columns.Count; j++)<br />
{<br />
subItem = new <strong>TreeListView</strong>SubItem("Item " + sufix + j.ToString());<br />
}<br />
}<br />
parentNode.SubItems.Add(subItem);<br />
As you can see from the code we have used the FlatNodes collection to cycle through nodes. This<br />
is a collection which holds linear structure of <strong>TreeListView</strong> control, instead hierarchical structure.<br />
Furthermore, the position and level of all nodes are persisted. It is best to use this collection if you<br />
have large set of nodes, and you need to perform some operation like searching. The performance<br />
is great.<br />
21
Style serialization and reuse<br />
If you want to create some predefined color schemes and apply it to the control at specific<br />
conditions, one way to do that is by serializing the control layout. You only would need to set the<br />
color and format styles and then save the layout in external xml file or database. After that, you<br />
only need to load the file which corresponds to the target color scheme.<br />
You can read more on how serialization is done at the end of this document in Serialization<br />
section.<br />
Visual Styles<br />
There are three predefined visual styles:<br />
• Classic - Used to render controls in Windows Classic control style<br />
• XP - Used to render controls in Windows XP control style<br />
• Vista - Used to render controls in Windows Vista control style<br />
By setting the VisualStyle property to some of the above options, different appearance is applied<br />
to the control.<br />
Themes<br />
If you want controls to adjust to the current theme and color scheme of windows operating<br />
system you need to set UseTheme property value to True. Depending of the current VisualStyle<br />
a predefined color scheme is used which corresponds to the current operating system color<br />
scheme.<br />
Note For creation of more advanced appearance, you can read in XML encoding section.<br />
22
Behavior<br />
Working with Columns<br />
Add/Remove operations<br />
The columns displayed in the <strong>TreeListView</strong> control are stored in Columns property. This is an<br />
object from <strong>TreeListView</strong>ColumnCollection class, which has several methods and events you can<br />
use to add, remove, clear or make any other operation that will change the collection. Here is a<br />
list of methods that you can use:<br />
• Add – adds a new column at the end of the collection<br />
• AddRange – add a set of column to the end of the collection<br />
• Clear – empties the list<br />
• Remove – deletes the column from the collection<br />
• RemoveAt – deletes the column that is located at specified location in the collection<br />
Here is an example how to add a new column programmatically to the collection:<br />
[VB]<br />
Imports <strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Lists<br />
. . .<br />
Dim column As New <strong>TreeListView</strong>Column("Header", "Footer")<br />
Me.treeListView1.Columns.Add(column)<br />
[C#]<br />
using <strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Lists;<br />
. . .<br />
<strong>TreeListView</strong>Column column = new <strong>TreeListView</strong>Column("Header", "Footer");<br />
this.treeListView1.Columns.Add(column);<br />
To insert a column at a specified position in the collection, use the Insert method:<br />
[VB]<br />
' Adds the node at sixth position in the collection<br />
Me.treeListView1.Columns.Insert(5, column)<br />
[C#]<br />
// Adds the node at sixth position in the collection<br />
this.treeListView1.Columns.Insert(5, column);<br />
When you add a new column to the <strong>TreeListView</strong> control, this process is accompanied with two<br />
events:<br />
• ColumnAdding – it is fired before column is added and can cancel the add operation<br />
• ColumnAdded – it is fired after the column is added<br />
To remove a column from the collection, two methods can be used:<br />
[VB]<br />
' Removes the column from the collection<br />
Me.treeListView1.Columns.Remove(column)<br />
23
' Removes the column located at the specified location from the collection<br />
Me.treeListView1.Columns.RemoveAt(5)<br />
[C#]<br />
// Removes the column from the collection<br />
this.treeListView1.Columns.Remove(node);<br />
// Removes the column located at the specified location from the collection<br />
this.treeListView1.Columns.RemoveAt(5);<br />
If you want to remove all columns, use the Clear method<br />
[VB]<br />
Me.treeListView1.Columns.Clear();<br />
[C#]<br />
this.treeListView1.Columns.Clear();<br />
How to add existing column collection<br />
If you have some predefined set of columns, and you want this set as a whole to be added to the<br />
<strong>TreeListView</strong> control, you can use AddRange method:<br />
[VB]<br />
Imports <strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Lists<br />
. . .<br />
Dim columns As <strong>TreeListView</strong>Column() = New <strong>TreeListView</strong>Column(2) {}<br />
For i As Integer = 0 To columns.Length - 1<br />
columns(i) = New <strong>TreeListView</strong>Column("Header " & i.ToString(), "Footer " &<br />
i.ToString())<br />
Next<br />
Me.treeListView1.Columns.AddRange(columns)<br />
[C#]<br />
using <strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Lists;<br />
. . .<br />
<strong>TreeListView</strong>Column[] columns = new <strong>TreeListView</strong>Column[3];<br />
for (int i = 0; i < columns.Length; i++)<br />
columns[i] = new <strong>TreeListView</strong>Column("Header " + i.ToString(), "Footer " +<br />
i.ToString());<br />
this.treeListView1.Columns.AddRange(columns);<br />
How to fix column to the left or right side of the control<br />
There are situations when you need some column(s) to be fixed on left or right side of the<br />
<strong>TreeListView</strong> control, while other columns remain scrollable. In this way the data in fixed columns<br />
will always remain visible, while scrolling the remaining area.<br />
24
By default columns are not fixed to either control side. There are three values for Fixed property<br />
from which you can choose how the column is fixed: None, Left and Right. In the code below the<br />
first column is fixed to the control left side<br />
[VB]<br />
column.Fixed = <strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Lists.ColumnFixedType.Left<br />
[C#]<br />
column.Fixed = <strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Lists.ColumnFixedType.Left;<br />
How to fix the column width<br />
In some cases you don’t want to allow to the end users to change the column width. This can be<br />
done by setting the FixedWidth property to True. However, at first the column width needs to be<br />
set.<br />
In the code below the first column has width fixed to 100 pixels<br />
[VB]<br />
column.Width = 100<br />
column.FixedWidth = True<br />
[C#]<br />
column.Width = 100;<br />
column.FixedWidth = true;<br />
Different types of column content<br />
In general columns contain text in their corresponding subitems. The type of data which column<br />
will present is determined with ContentType property. There are five different values from which<br />
you can choose:<br />
• CheckBox – the column will shown a built-in CheckBox control<br />
• ComboBox – the column will shown a built-in ComboBox control<br />
• Control – the column will shown a custom control<br />
• Custom – a custom layout created with XML tags can be shown<br />
• DateTime – the column will shown a built-in DateTimePicker control<br />
• Image – the column will shown an image<br />
• NumericUpDown – the column will shown a built-in NumericUpDown control<br />
• ProgressBar – the column will shown a built-in ProgressBar control<br />
• RatingControl – the column will shown a built-in RatingControl<br />
• Text – default, the column will shown a label<br />
• TextControl – the column will shown a built-in TextControl<br />
Depending of this property value, the subitem which belongs to the specified column shows the<br />
specific data in its space. If there is no data which can be converted to specified type, or there is<br />
no subitem which corresponds to the column, nothing is shown.<br />
In the following examples we will show you how to create columns with different content types. At<br />
first we need to fill the <strong>TreeListView</strong> control with some columns, nodes and subitems:<br />
25
[VB]<br />
Imports <strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Lists<br />
. . .<br />
Private Sub InitList(ByVal sender As Object, ByVal e As EventArgs)<br />
' Create three columns with header and footer description<br />
Dim column As <strong>TreeListView</strong>Column = Nothing<br />
For j As Integer = 0 To 1<br />
column = New <strong>TreeListView</strong>Column("Header " & j.ToString(), "Footer " &<br />
j.ToString())<br />
Me.treeListView1.Columns.Add(column)<br />
Next<br />
' Reset the node counter<br />
nodeIndex = 0<br />
' Create root nodes<br />
Dim node As <strong>TreeListView</strong>Node = Nothing<br />
For i As Integer = 0 To 2<br />
node = New <strong>TreeListView</strong>Node("Node " & i.ToString())<br />
nodeIndex += 1<br />
' Create subitems for this node<br />
CreateSubItems(node, i.ToString())<br />
' Create child nodes for this node<br />
CreateSubNodes(node, 0, i.ToString())<br />
Me.treeListView1.Nodes.Add(node)<br />
Next<br />
Me.treeListView1.UpdateLayout()<br />
End Sub<br />
Private Sub CreateSubItems(ByVal parentNode As <strong>TreeListView</strong>Node, ByVal sufix As<br />
String)<br />
' Create subitems for specified node<br />
Dim subItem As <strong>TreeListView</strong>SubItem = Nothing<br />
For j As Integer = 0 To Me.treeListView1.Columns.Count - 1<br />
subItem = New <strong>TreeListView</strong>SubItem()<br />
Select Case Me.treeListView1.Columns(j).ContentType<br />
Case Else<br />
subItem.Text = ("Item " & sufix) + j.ToString()<br />
Exit Select<br />
End Select<br />
parentNode.SubItems.Add(subItem)<br />
Next<br />
End Sub<br />
Private Sub CreateSubNodes(ByVal parentNode As <strong>TreeListView</strong>Node, ByVal level As<br />
Integer, ByVal sufix As String)<br />
' In this example only two levels in hierarchy are allowed<br />
If level = 2 Then<br />
Exit Sub<br />
Else<br />
26
' Create child nodes for specified node<br />
Dim node As <strong>TreeListView</strong>Node = Nothing<br />
For i As Integer = 0 To 1<br />
node = New <strong>TreeListView</strong>Node(("Node " & sufix) + i.ToString())<br />
nodeIndex += 1<br />
' Create subitems for this node<br />
CreateSubItems(node, sufix + i.ToString())<br />
' Create child nodes for this node<br />
CreateSubNodes(node, level + 1, sufix + i.ToString())<br />
parentNode.Nodes.Add(node)<br />
Next<br />
End If<br />
End Sub<br />
[C#]<br />
using <strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Lists;<br />
. . .<br />
private void InitList(object sender, EventArgs e)<br />
{<br />
// Create two columns with header and footer description<br />
<strong>TreeListView</strong>Column column = null;<br />
for (int j = 0; j < 2; j++)<br />
{<br />
column = new <strong>TreeListView</strong>Column("Header " + j.ToString(), "Footer " +<br />
j.ToString());<br />
}<br />
}<br />
this.treeListView1.Columns.Add(column);<br />
// Reset the node counter<br />
nodeIndex = 0;<br />
// Create root nodes<br />
<strong>TreeListView</strong>Node node = null;<br />
for (int i = 0; i < 3; i++)<br />
{<br />
node = new <strong>TreeListView</strong>Node("Node " + i.ToString());<br />
nodeIndex++;<br />
}<br />
// Create subitems for this node<br />
CreateSubItems(node, i.ToString());<br />
// Create child nodes for this node<br />
CreateSubNodes(node, 0, i.ToString());<br />
this.treeListView1.Nodes.Add(node);<br />
this.treeListView1.UpdateLayout();<br />
private void CreateSubItems(<strong>TreeListView</strong>Node parentNode,string sufix)<br />
{<br />
// Create subitems for specified node<br />
27
}<br />
<strong>TreeListView</strong>SubItem subItem = null;<br />
for (int j = 0; j < this.treeListView1.Columns.Count; j++)<br />
{<br />
subItem = new <strong>TreeListView</strong>SubItem();<br />
}<br />
switch (this.treeListView1.Columns[j].ContentType)<br />
{<br />
default:<br />
subItem.Text = "Item " + sufix + j.ToString();<br />
break;<br />
}<br />
parentNode.SubItems.Add(subItem);<br />
private void CreateSubNodes(<strong>TreeListView</strong>Node parentNode, int level, string sufix)<br />
{<br />
// In this example only two levels in hierarchy are allowed<br />
if (level == 2)<br />
return;<br />
else<br />
{<br />
// Create child nodes for specified node<br />
<strong>TreeListView</strong>Node node = null;<br />
for (int i = 0; i < 2; i++)<br />
{<br />
node = new <strong>TreeListView</strong>Node("Node " + sufix + i.ToString());<br />
nodeIndex++;<br />
}<br />
}<br />
}<br />
// Create subitems for this node<br />
CreateSubItems(node, sufix + i.ToString());<br />
// Create child nodes for this node<br />
CreateSubNodes(node, level + 1, sufix + i.ToString());<br />
parentNode.Nodes.Add(node);<br />
The above code will create two columns with several nodes and two subitems in each node. All<br />
data in column will be labels.<br />
How to show custom images in column<br />
By changing a little bit above code sample, we will set the second column to show images. The<br />
changes are marked in Red:<br />
[VB]<br />
Private Sub InitList(ByVal sender As Object, ByVal e As EventArgs)<br />
' Create three columns with header and footer description<br />
Dim column As <strong>TreeListView</strong>Column = Nothing<br />
For j As Integer = 0 To 1<br />
column = New <strong>TreeListView</strong>Column("Header " & j.ToString(), "Footer " &<br />
j.ToString())<br />
28
Select Case j<br />
' Set the second column to show custom controls<br />
Case 1<br />
column.ContentType = ColumnContentType.Image<br />
Exit Select<br />
' Make a first column a little wider<br />
Case Else<br />
column.Width = 100<br />
Exit Select<br />
End Select<br />
Me.treeListView1.Columns.Add(column)<br />
Next<br />
. . .<br />
End Sub<br />
Private Sub CreateSubItems(ByVal parentNode As <strong>TreeListView</strong>Node, ByVal sufix As<br />
String)<br />
' Create subitems for specified node<br />
Dim subItem As <strong>TreeListView</strong>SubItem = Nothing<br />
For j As Integer = 0 To Me.treeListView1.Columns.Count - 1<br />
subItem = New <strong>TreeListView</strong>SubItem()<br />
Select Case Me.treeListView1.Columns(j).ContentType<br />
Case ColumnContentType.Image<br />
subItem.Image = imgCountries.Images(nodeIndex Mod 9)<br />
Exit Select<br />
Case Else<br />
subItem.Text = ("Item " & sufix) + j.ToString()<br />
Exit Select<br />
End Select<br />
. . .<br />
End Sub<br />
[C#]<br />
private void InitList(object sender, EventArgs e)<br />
{<br />
// Create two columns with header and footer description<br />
<strong>TreeListView</strong>Column column = null;<br />
for (int j = 0; j < 2; j++)<br />
{<br />
column = new <strong>TreeListView</strong>Column("Header " + j.ToString(), "Footer " +<br />
j.ToString());<br />
switch (j)<br />
{<br />
// Set the second column to show images<br />
case 1:<br />
column.ContentType = ColumnContentType.Image;<br />
break;<br />
// Make a first column a little wider<br />
default:<br />
29
}<br />
}<br />
}<br />
. . .<br />
column.Width = 100;<br />
break;<br />
this.treeListView1.Columns.Add(column);<br />
private void CreateSubItems(<strong>TreeListView</strong>Node parentNode,string sufix)<br />
{<br />
// Create subitems for specified node<br />
<strong>TreeListView</strong>SubItem subItem = null;<br />
for (int j = 0; j < this.treeListView1.Columns.Count; j++)<br />
{<br />
subItem = new <strong>TreeListView</strong>SubItem();<br />
}<br />
switch (this.treeListView1.Columns[j].ContentType)<br />
{<br />
case ColumnContentType.Image:<br />
subItem.Image = imgCountries.Images[nodeIndex % 9];<br />
break;<br />
}<br />
. . .<br />
default:<br />
subItem.Text = "Item " + sufix + j.ToString();<br />
break;<br />
For images we are using an ImageList which contains a set of 9 images. Because of this you will<br />
notice that we use the following code line:<br />
[VB]<br />
subItem.Image = imgCountries.Images(nodeIndex Mod 9)<br />
[C#]<br />
subItem.Image = imgCountries.Images[nodeIndex % 9];<br />
The result is:<br />
30
How to show custom control in column<br />
<strong>IntegralUI</strong> <strong>TreeListView</strong> control has a unique feature that allows any custom control to be inserted<br />
in every column, node or subitem. We will show you how a ProgressBar control can be included in<br />
each subitem which corresponds to the second column. The changes are marked in Red:<br />
[VB]<br />
Private Sub InitList(ByVal sender As Object, ByVal e As EventArgs)<br />
' Create three columns with header and footer description<br />
Dim column As <strong>TreeListView</strong>Column = Nothing<br />
For j As Integer = 0 To 2<br />
column = New <strong>TreeListView</strong>Column("Header " & j.ToString(), "Footer " &<br />
j.ToString())<br />
Select Case j<br />
' Set the second column to show custom controls<br />
Case 1<br />
column.ContentType = ColumnContentType.Image<br />
Exit Select<br />
' Set the second column to show custom controls<br />
Case 2<br />
column.ContentType = ColumnContentType.Control<br />
column.ContentControlVisibility =<br />
ContentControlVisibility.AlwaysVisible<br />
Exit Select<br />
Case Else<br />
' Make a first column a little wider<br />
column.Width = 100<br />
Exit Select<br />
End Select<br />
Me.treeListView1.Columns.Add(column)<br />
Next<br />
. . .<br />
31
End Sub<br />
Private Sub CreateSubItems(ByVal parentNode As <strong>TreeListView</strong>Node, ByVal sufix As<br />
String)<br />
' Create subitems for specified node<br />
Dim subItem As <strong>TreeListView</strong>SubItem = Nothing<br />
For j As Integer = 0 To Me.treeListView1.Columns.Count - 1<br />
subItem = New <strong>TreeListView</strong>SubItem()<br />
Select Case Me.treeListView1.Columns(j).ContentType<br />
Case ColumnContentType.Image<br />
subItem.Image = imgCountries.Images(nodeIndex Mod 9)<br />
Exit Select<br />
Case ColumnContentType.Control<br />
Dim pBar As New ProgressBar()<br />
pBar.Size = New Size(100, 16)<br />
progressValue = RandomValue(progressValue)<br />
pBar.Value = progressValue<br />
subItem.Control = pBar<br />
Exit Select<br />
Case Else<br />
subItem.Text = ("Item " & sufix) + j.ToString()<br />
Exit Select<br />
End Select<br />
. . .<br />
End Sub<br />
Private Function RandomValue(ByVal value As Integer) As Integer<br />
Dim gen As New Random()<br />
Dim range As Integer = (100 - value)<br />
Return gen.[Next](range)<br />
End Function<br />
32
[C#]<br />
private void InitList(object sender, EventArgs e)<br />
{<br />
// Create two columns with header and footer description<br />
<strong>TreeListView</strong>Column column = null;<br />
for (int j = 0; j < 3; j++)<br />
{<br />
column = new <strong>TreeListView</strong>Column("Header " + j.ToString(), "Footer " +<br />
j.ToString());<br />
switch (j)<br />
{<br />
// Set the second column to show custom controls<br />
case 1:<br />
column.ContentType = ColumnContentType.Image;<br />
break;<br />
// Set the second column to show custom controls<br />
case 2:<br />
column.ContentType = ColumnContentType.Control;<br />
column.ContentControlVisibility =<br />
ContentControlVisibility.AlwaysVisible;<br />
break;<br />
}<br />
}<br />
}<br />
. . .<br />
// Make a first column a little wider<br />
default:<br />
column.Width = 100;<br />
break;<br />
this.treeListView1.Columns.Add(column);<br />
private void CreateSubItems(<strong>TreeListView</strong>Node parentNode,string sufix)<br />
{<br />
// Create subitems for specified node<br />
<strong>TreeListView</strong>SubItem subItem = null;<br />
for (int j = 0; j < this.treeListView1.Columns.Count; j++)<br />
{<br />
subItem = new <strong>TreeListView</strong>SubItem();<br />
switch (this.treeListView1.Columns[j].ContentType)<br />
{<br />
case ColumnContentType.Image:<br />
subItem.Image = imgCountries.Images[nodeIndex % 9];<br />
break;<br />
case ColumnContentType.Control:<br />
ProgressBar pBar = new ProgressBar();<br />
pBar.Size = new Size(100, 16);<br />
progressValue = RandomValue(progressValue);<br />
pBar.Value = progressValue;<br />
subItem.Control = pBar;<br />
break;<br />
default:<br />
33
}<br />
}<br />
. . .<br />
subItem.Text = "Item " + sufix + j.ToString();<br />
break;<br />
private int RandomValue(int value)<br />
{<br />
Random gen = new Random();<br />
int range = (100 - value);<br />
return gen.Next(range);<br />
}<br />
Also, it is important to menton that when ContentType is set to Control, the visibility of the control<br />
is determined by another property, ContentControlVisibility. There are four ways to show the<br />
control:<br />
• None – the control is not visible<br />
• OnClick – the control will become visible when the subitem is clicked<br />
• OnHover – the control will become visible when mouse hovers over subitem<br />
• AlwaysVisible – the control is visible<br />
How to show custom objects in column<br />
In many cases it’s not enough to show only a single object in column. There are scenarios where<br />
you need to place different objects like text, images, hyperlinks, controls etc. and arrange then in<br />
custom layouts.<br />
34
We will show you how by using XML tags various objects can be placed in every subitem which<br />
belongs to a column with specified custom content. For this example we are going to use image,<br />
hyperlink and checkbox.<br />
[VB]<br />
Private Sub button3_Click(ByVal sender As Object, ByVal e As EventArgs)<br />
' Create three columns with header and footer description<br />
Dim column As <strong>TreeListView</strong>Column = Nothing<br />
For j As Integer = 0 To 3<br />
column = New <strong>TreeListView</strong>Column("Header " & j.ToString(), "Footer " &<br />
j.ToString())<br />
Select Case j<br />
' Set the second column to show custom controls<br />
Case 1<br />
column.ContentType = ColumnContentType.Image<br />
Exit Select<br />
' Set the third column to show custom controls<br />
Case 2<br />
column.ContentType = ColumnContentType.Control<br />
column.ContentControlVisibility =<br />
ContentControlVisibility.AlwaysVisible<br />
Exit Select<br />
' Set the fourth column to show custom objects<br />
Case 3<br />
column.ContentType = ColumnContentType.[Custom]<br />
column.Width = 120<br />
Exit Select<br />
Case Else<br />
' Make a first column a little wider<br />
column.Width = 100<br />
Exit Select<br />
End Select<br />
Me.treeListView1.Columns.Add(column)<br />
Next<br />
. . .<br />
End Sub<br />
Private Sub CreateSubItems(ByVal parentNode As <strong>TreeListView</strong>Node, ByVal sufix As<br />
String)<br />
' Create subitems for specified node<br />
Dim subItem As <strong>TreeListView</strong>SubItem = Nothing<br />
For j As Integer = 0 To Me.treeListView1.Columns.Count - 1<br />
subItem = New <strong>TreeListView</strong>SubItem()<br />
Select Case Me.treeListView1.Columns(j).ContentType<br />
Case ColumnContentType.Image<br />
subItem.Image = imgCountries.Images(nodeIndex Mod 9)<br />
Exit Select<br />
Case ColumnContentType.Control<br />
Dim pBar As New ProgressBar()<br />
pBar.Size = New Size(100, 16)<br />
35
progressValue = RandomValue(progressValue)<br />
pBar.Value = progressValue<br />
subItem.Control = pBar<br />
Exit Select<br />
Case ColumnContentType.[Custom]<br />
' Create and add a checkbox to the subitem<br />
Dim cBox As New CheckBox()<br />
cBox.Size = New Size(13, 13)<br />
If nodeIndex Mod 3 = 1 Then<br />
cBox.Checked = True<br />
End If<br />
subItem.Controls.Add(cBox)<br />
' Set the image index<br />
Dim imgIndex As Integer = nodeIndex Mod 9<br />
' Create a custom content<br />
Dim content As String = ""<br />
content += "More info"<br />
content += ""<br />
content += ""<br />
' Add the created content to the subitem<br />
subItem.Content = content<br />
Exit Select<br />
Case Else<br />
subItem.Text = ("Item " & sufix) + j.ToString()<br />
Exit Select<br />
End Select<br />
. . .<br />
End Sub<br />
36
[C#]<br />
private void InitList(object sender, EventArgs e)<br />
{<br />
// Create two columns with header and footer description<br />
<strong>TreeListView</strong>Column column = null;<br />
for (int j = 0; j < 4; j++)<br />
{<br />
column = new <strong>TreeListView</strong>Column("Header " + j.ToString(), "Footer " +<br />
j.ToString());<br />
switch (j)<br />
{<br />
// Set the second column to show custom controls<br />
case 1:<br />
column.ContentType = ColumnContentType.Image;<br />
break;<br />
// Set the third column to show custom controls<br />
case 2:<br />
column.ContentType = ColumnContentType.Control;<br />
column.ContentControlVisibility =<br />
ContentControlVisibility.AlwaysVisible;<br />
break;<br />
}<br />
}<br />
}<br />
. . .<br />
// Set the fourth column to show custom objects<br />
case 3:<br />
column.ContentType = ColumnContentType.Custom;<br />
column.Width = 120;<br />
break;<br />
// Make a first column a little wider<br />
default:<br />
column.Width = 100;<br />
break;<br />
this.treeListView1.Columns.Add(column);<br />
private void CreateSubItems(<strong>TreeListView</strong>Node parentNode,string sufix)<br />
{<br />
// Create subitems for specified node<br />
<strong>TreeListView</strong>SubItem subItem = null;<br />
for (int j = 0; j < this.treeListView1.Columns.Count; j++)<br />
{<br />
subItem = new <strong>TreeListView</strong>SubItem();<br />
switch (this.treeListView1.Columns[j].ContentType)<br />
{<br />
case ColumnContentType.Image:<br />
subItem.Image = imgCountries.Images[nodeIndex % 9];<br />
break;<br />
case ColumnContentType.Control:<br />
ProgressBar pBar = new ProgressBar();<br />
pBar.Size = new Size(100, 16);<br />
37
progressValue = RandomValue(progressValue);<br />
pBar.Value = progressValue;<br />
subItem.Control = pBar;<br />
break;<br />
case ColumnContentType.Custom:<br />
// Create and add a checkbox to the subitem<br />
CheckBox cBox = new CheckBox();<br />
cBox.Size = new Size(13, 13);<br />
if (nodeIndex % 3 == 1)<br />
cBox.Checked = true;<br />
subItem.Controls.Add(cBox);<br />
// Set the image index<br />
int imgIndex = nodeIndex % 9;<br />
// Create a custom content<br />
String content = "";<br />
content += "More info";<br />
content += "";<br />
content += "";<br />
}<br />
}<br />
. . .<br />
// Add the created content to the subitem<br />
subItem.Content = content;<br />
break;<br />
default:<br />
subItem.Text = "Item " + sufix + j.ToString();<br />
break;<br />
To display the images in subitems we have used an ImageList component added to the<br />
<strong>TreeListView</strong>.ImageList property. The result is:<br />
38
Working with Nodes<br />
Add/Remove operations<br />
The nodes displayed in the <strong>TreeListView</strong> control are stored in Nodes property. This is an object<br />
from <strong>TreeListView</strong>NodeCollection class, which has several methods and events you can use to add,<br />
remove, clear or make any other operation that will change the collection. Here is a list of<br />
methods that you can use:<br />
• Add – adds a new node at the end of the collection<br />
• AddRange – add a set of nodes to the end of the collection<br />
• Clear – empties the list<br />
• Remove – deletes the node from the collection<br />
• RemoveAt – deletes the node that is located at specified location in the collection<br />
Here is an example how to add a new node programmatically to the collection:<br />
[VB]<br />
Dim node As New <strong>TreeListView</strong>Node(“New node”)<br />
Me.treeListView1.Node.Add(node)<br />
[C#]<br />
<strong>TreeListView</strong>Node node = new <strong>TreeListView</strong>Node("New node");<br />
this.treeListView1.Nodes.Add(node);<br />
To insert this node at a specified position in the collection, use the Insert method:<br />
[VB]<br />
' Adds the node at sixth position in the collection<br />
Me.treeListView1.Nodes.Insert(5, node)<br />
[C#]<br />
// Adds the node at sixth position in the collection<br />
this.treeListView1.Nodes.Insert(5, node);<br />
When you add a new node to the <strong>TreeListView</strong> control, this process is accompanied with two<br />
events:<br />
• NodeAdding – it is fired before node is added and can be cancel the add operation<br />
• NodeAdded – it is fired after the node is added<br />
To remove a node from the collection, two methods can be used:<br />
[VB]<br />
' Removes the node from the collection<br />
Me.treeListView1.Nodes.Remove(node)<br />
' Removes the node located at the specified location from the collection<br />
Me.treeListView1.Nodes.RemoveAt(5)<br />
[C#]<br />
// Removes the node from the collection<br />
this.treeListView1.Nodes.Remove(node);<br />
// Removes the node located at the specified location from the collection<br />
this.treeListView1.Nodes.RemoveAt(5);<br />
If you wan to remove all nodes, use the Clear method<br />
39
[VB]<br />
Me.treeListView1.Nodes.Clear();<br />
[C#]<br />
this.treeListView1.Nodes.Clear();<br />
How to add existing node collection<br />
If you want some predefined set of nodes, and you want this set as a whole to be added to the<br />
<strong>TreeListView</strong> control, you can use AddRange method:<br />
[VB]<br />
Imports <strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Lists<br />
. . .<br />
Dim nodes As <strong>TreeListView</strong>Node() = New Node(6) {}<br />
For i As Integer = 0 To 6<br />
nodes(i) = New <strong>TreeListView</strong>Node("Item " & i.ToString())<br />
Next<br />
Me.treeListView1.Nodes.AddRange(nodes)<br />
[C#]<br />
using <strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Lists;<br />
. . .<br />
<strong>TreeListView</strong>Node[] nodes = new <strong>TreeListView</strong>Node[7];<br />
for (int i = 0; i < 7; i++)<br />
nodes[i] = new <strong>TreeListView</strong>Node("Item " + i.ToString());<br />
this.treeListView1.Nodes.AddRange(nodes);<br />
How to edit the node text<br />
During runtime you can allow to users to edit the node text and change it. This can be done by<br />
setting the LabelEdit property to True. After that whenever the user clicks on the node and<br />
releases the mouse button, a TextBox will appear in which the node text can be edited.<br />
If you want to start editing process in other way, you need to use BeginEdit and EndEdit<br />
methods. In the following example we will show how to programmatically start editing process:<br />
[VB]<br />
If Me.<strong>TreeListView</strong>1.SelectedNode IsNot Nothing Then<br />
Me.<strong>TreeListView</strong>1.LabelEdit = True<br />
Me.<strong>TreeListView</strong>1.SelectedNode.BeginEdit()<br />
End If<br />
[C#]<br />
if (this.treeListView1.SelectedNode != null)<br />
{<br />
this.treeListView1.LabelEdit = true;<br />
this.treeListView1.SelectedNode.BeginEdit();<br />
40
}<br />
The edit process is accompanied by two events:<br />
• BeforeLabelEdit – it is fired before the TextEditor is shown and editing beggins<br />
• AfterLabelEdit – it is fired when TextEditor closes and just before the new text is<br />
applied to the node Text property<br />
In order to cancel the current edit process, you can simply press the ESC key or by handle the<br />
AfterLabelEdit event. In the following example the edit is allowed only for labels which don’t<br />
contain some characters:<br />
[VB]<br />
Imports <strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Lists<br />
. . .<br />
Private Sub treeListView1_AfterLabelEdit(ByVal sender As Object, ByVal e As<br />
<strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.ObjectEditEventArgs)<br />
If TypeOf e.[Object] Is <strong>TreeListView</strong>Node Then<br />
Dim node As <strong>TreeListView</strong>Node = DirectCast(e.[Object], <strong>TreeListView</strong>Node)<br />
If e.Label IsNot Nothing Then<br />
If e.Label.Length > 0 Then<br />
If e.Label.IndexOfAny(New Char() {"@"c, "."c, ","c, "!"c}) >= 0 Then<br />
' Cancel the label edit action, inform the user, and<br />
' place the node in edit mode again.<br />
e.Cancel = True<br />
MessageBox.Show("Invalid node label." & vbLf & "The invalid<br />
characters are: '@','.', ',', '!'", "Node Label Edit")<br />
node.BeginEdit()<br />
End If<br />
Else<br />
' Cancel the label edit action, inform the user, and<br />
' place the node in edit mode again.<br />
e.Cancel = True<br />
MessageBox.Show("Invalid node label." & vbLf & "The label cannot be<br />
blank", "Node Label Edit")<br />
node.BeginEdit()<br />
End If<br />
End If<br />
End If<br />
End Sub<br />
[C#]<br />
using <strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Lists;<br />
. . .<br />
private void treeListView1_AfterLabelEdit(object sender,<br />
<strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.ObjectEditEventArgs e)<br />
{<br />
if (e.Object is <strong>TreeListView</strong>Node)<br />
{<br />
<strong>TreeListView</strong>Node node = (<strong>TreeListView</strong>Node)e.Object;<br />
41
if (e.Label != null)<br />
{<br />
if (e.Label.Length > 0)<br />
{<br />
if (e.Label.IndexOfAny(new char[] { '@', '.', ',', '!' }) >= 0)<br />
{<br />
// Cancel the label edit action, inform the user, and<br />
// place the node in edit mode again.<br />
e.Cancel = true;<br />
MessageBox.Show("Invalid node label.\n" + "The invalid<br />
characters are: '@','.', ',', '!'", "Node Label Edit");<br />
node.BeginEdit();<br />
}<br />
}<br />
else<br />
{<br />
// Cancel the label edit action, inform the user, and<br />
// place the node in edit mode again.<br />
e.Cancel = true;<br />
MessageBox.Show("Invalid node label.\nThe label cannot be blank",<br />
"Node Label Edit");<br />
node.BeginEdit();<br />
}<br />
}<br />
}<br />
}<br />
Checked nodes<br />
In order to display checkboxes to the nodes, the CheckBoxes property of the <strong>TreeListView</strong><br />
control must be set to True. Every node has a check box shown to the left side of the node space.<br />
Their visibility is controlled by CheckBoxVisible property. In this way, you can decide which nodes<br />
will have checkbox. This is useful for example when you want some node to behave like a header<br />
for other nodes.<br />
The check box can display two or three state values. By default the two-state (checked and<br />
unchecked) behavior is active. If you want to have three-state behavior, at first you need to set<br />
the CheckMode to ThreeState value. Whenever user clicks inside the check box space, it will<br />
cycle the state of the check box through Unchecked, Indeterminate and Checked values.<br />
In some cases you will also want to change the check box state by node selection. In order to do<br />
that, set the AllowSelectionCheck property to True.<br />
The set of checked nodes (only those with CheckState set to Checked) is stored in<br />
CheckedItems collection. This collection is very useful when you want to examine only nodes<br />
that are currently checked.<br />
How to preserve checked nodes<br />
42
In some cases you may want to preserve the collection of checked nodes unchanged. For<br />
example, there may be custom operation which will indirectly change the CheckState of the<br />
nodes, and in this way the CheckedItems collection. In order to prevent this from happening, we<br />
have added a PreserveCheckState property. With it you can preserve the current collection, run<br />
your custom operation without side effects, and then set back this property to its original value.<br />
For example:<br />
[VB]<br />
Private Sub button1_Click(ByVal sender As Object, ByVal e As EventArgs)<br />
Me.treeListView1.PreserveCheckState = True<br />
Me.treeListView1.SelectedNode = Me.treeListView1.Nodes(1)<br />
Me.treeListView1.PreserveCheckState = False<br />
End Sub<br />
Private Sub treeListView1_AfterSelect(ByVal sender As Object, ByVal e As<br />
<strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.ObjectEventArgs)<br />
If TypeOf e.[Object] Is <strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Lists.<strong>TreeListView</strong>Node Then<br />
Dim node As <strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Lists.<strong>TreeListView</strong>Node = DirectCast(e.<br />
[Object], <strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Lists.<strong>TreeListView</strong>Node)<br />
Me.treeListView1.CheckedNodes.Clear()<br />
node.Checked = True<br />
End If<br />
End Sub<br />
[C#]<br />
private void button1_Click(object sender, EventArgs e)<br />
{<br />
this.treeListView1.PreserveCheckState = true;<br />
this.treeListView1.SelectedNode = this.treeListView1.Nodes[1];<br />
this.treeListView1.PreserveCheckState = false;<br />
}<br />
private void treeListView1_AfterSelect(object sender,<br />
<strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.ObjectEventArgs e)<br />
{<br />
if (e.Object is <strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Lists.<strong>TreeListView</strong>Node)<br />
{<br />
<strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Lists.<strong>TreeListView</strong>Node node =<br />
(<strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Lists.<strong>TreeListView</strong>Node)e.Object;<br />
}<br />
}<br />
this.treeListView1.CheckedNodes.Clear();<br />
node.Checked = true;<br />
In this example we have a <strong>TreeListView</strong> with some nodes in it. Whenever a button is clicked the<br />
second node is selected and checked. But along with this by calling the Clear method, we try to<br />
remove all checked nodes from CheckedNodes collection. Because we have set<br />
PreserveCheckState to True, this collection will remain intact.<br />
43
Selected nodes<br />
Multiple selection<br />
The control supports four different modes for node selection. They are controlled from the<br />
SelectionMode property, which can have following values:<br />
• None – there is no selection<br />
• One – only one node can be selected<br />
• MultiSimple – selection is performed with single mouse click<br />
• MultiExtended – selection is perfomed with use of CTRL or SHIFT keys<br />
In order to have multiple node selection, the SelectionMode must be set either to MultiSimple or<br />
MultiExtended value.<br />
Whenever there is a selection, nodes that are currently selected are stored in SelectedNodes<br />
collection. This collection is very useful when you want to examine only nodes that are currently<br />
selected.<br />
Hover selection<br />
In some cases you may want to allow nodes to be selected while mouse cursor hovers over them.<br />
This functionality is built-in the code, and in order to allow it, just set the HoverSelection<br />
property to True.<br />
How to preserve selection<br />
In some cases you may want to preserve the collection of selected nodes unchanged. For<br />
example, there may be custom operation which will indirectly change the Selected state of the<br />
node, and in this way the SelectedNodes collection. In order to prevent this from happening, we<br />
have added a PreserveSelection property. With it you can preserve the current collection, run<br />
your custom operation without side effects, and then set back this property to its original value.<br />
For example:<br />
[VB]<br />
Private Sub button1_Click(ByVal sender As Object, ByVal e As EventArgs)<br />
Me.treeListView1.PreserveSelection = True<br />
Me.treeListView1.SelectedNodes.Clear()<br />
Me.treeListView1.SelectedNode = Me.treeListView1.Nodes(1)<br />
Me.treeListView1.PreserveSelection = False<br />
End Sub<br />
[C#]<br />
private void button1_Click(object sender, EventArgs e)<br />
{<br />
this.treeListView1.PreserveSelection = true;<br />
this.treeListView1.SelectedNodes.Clear();<br />
this.treeListView1.SelectedNode = this.treeListView1.Nodes[1];<br />
this.treeListView1.PreserveSelection = false;<br />
}<br />
In this example we have a <strong>TreeListView</strong> with some nodes in it. Whenever a button is clicked the<br />
second node is selected. But along with this by calling the Clear method, we try to remove all<br />
44
selected nodes from SelectedNodes collection. Because we have set PreserveSelection to True,<br />
this collection will remain intact. This only works in multiple selection mode.<br />
Working with SubItems<br />
Add/Remove operations<br />
Every node contains a set of subitems. They are used to show a row of data in columns. Each<br />
subitem is linked with the column at which it will be presented. If you reorder columns, then<br />
automatically subitems are reordered in the node.<br />
Here is a list of methods that you can use with collection of subitems:<br />
• Add – adds a new subitem at the end of the collection<br />
• AddRange – add a set of subitems to the end of the collection<br />
• Clear – empties the list<br />
• Remove – deletes the subitem from the collection<br />
• RemoveAt – deletes the subitem that is located at specified location in the collection<br />
Here is an example how to add a new subitem programmatically to the collection:<br />
[VB]<br />
Dim subitem As New <strong>TreeListView</strong>SubItem(“New subitem”)<br />
node.SubItems.Add(subitem)<br />
[C#]<br />
<strong>TreeListView</strong>SubItem subitem = new <strong>TreeListView</strong>SubItem("New subitem");<br />
node.SubItems.Add(subitem);<br />
To insert this subitem at a specified position in the collection, use the Insert method:<br />
[VB]<br />
' Adds the subitem at third position in the collection<br />
node.SubItems.Insert(2, subitem)<br />
[C#]<br />
// Adds the subitem at third position in the collection<br />
node.SubItems.Insert(2, subitem);<br />
To remove a subitem from the collection, two methods can be used:<br />
[VB]<br />
' Removes the subitem from the collection<br />
node.SubItems.Remove(subitem)<br />
' Removes the subitem located at the specified location from the collection<br />
node.SubItems.RemoveAt(2)<br />
[C#]<br />
// Removes the subitem from the collection<br />
node.SubItems.Remove(subitem);<br />
// Removes the subitem located at the specified location from the collection<br />
node.SubItems.RemoveAt(2);<br />
45
If you wan to remove all subitems, use the Clear method<br />
[VB]<br />
node.SubItems.Clear();<br />
[C#]<br />
node.SubItems.Clear();<br />
Standard selection<br />
By default selection is only applied to nodes as a whole. In order to have a precific subitem<br />
selected, at first the AllowSubItemSelection needs to be set to True. This will allow specific<br />
subitem to be selected when you click in their space.<br />
All selected subitems are stored in SelectedSubItems collection. This collection can be used if you<br />
to search only through selected subitems, regardless at which node belongs. As with nodes, there<br />
is also a property SelectedSubItem which holds the current selected subitem.<br />
Frame selection<br />
Subitems can also be selected by creating a frame arround them. Every subitem which has his<br />
bounds contained as part or as a whole in the created frame region, will be automatically selected<br />
at the end of the operation. In order to allow this operation to start, the AllowFrameSelection<br />
property needs to be set to True. The frame selection is also dependent on the<br />
AllowSubItemSelection property. There is no reason to start this operation if this property is set to<br />
False.<br />
Here is a picture which shows this:<br />
Start of a frame selection End of a frame selection<br />
Drag&Drop operations<br />
The <strong>IntegralUI</strong> <strong>TreeListView</strong> control has built-in support for standard drag&drop operations like:<br />
drag and drop of single node, copy/move the node/s from one <strong>TreeListView</strong> to other controls etc.<br />
In the following sections we will give you information on how you can use various permissions<br />
during drag&drop operations, and how to extend this by creating your own custom operation.<br />
46
Use of permissions<br />
Here is a brief description on various properties that are used during drag&drop:<br />
• AllowDrag – Gives permission to node/s to be dragged<br />
• AllowDrop – Gives permission to the control to accept node/s during drag&drop<br />
• DragDropMode – Determines the type of drag&drop operation<br />
• DragDropReorder – Determines whether a reordering of nodes is allowed during<br />
drag&drop<br />
• ShowDropMarker – Determines whether the marker is shown that represents the current<br />
drop position<br />
By default drag&drop is disabled. In order to start dragging of node/s, the AllowDrag property<br />
must be set to True. However, in order for dragged nodes to be dropped, the AllowDrop<br />
property must also be set to True. We have deliberately separated the control over drag&drop<br />
operation in two states, because in some cases you may want to have one <strong>TreeListView</strong> control<br />
from which nodes can only be dragged, and other <strong>TreeListView</strong> control to which nodes can only be<br />
dropped.<br />
By default there is a predefined drag&drop operation which handles all of standard cases. In order<br />
to create your own operation, the DragDropMode must be set to Custom. This case is described<br />
in detail in the next section.<br />
If you don’t want to appear the drop marker during drag&drop, the best is to disable it from the<br />
ShowDropMarker property. In other case, this marker will be shown. You can change the color<br />
of this marker from the ColorStyle of the <strong>TreeListView</strong>, by changing the NodePosColor property.<br />
How to create a custom drag&drop operation<br />
If the default drag&drop operaton doesn’t give you the solution you want, you can always create<br />
your own custom operation.<br />
In order to do that, you need to do the following:<br />
1. At first, you need to set the DragDropMode to Custom<br />
2. Handle the ItemDrag event and start the drag&drop operation<br />
3. Handle the DragOver and DragDrop events<br />
4. Optionally, handle other drag&drop events, like: DragEnter, DragLeave,<br />
QueryContinueDrag, etc.<br />
Here is some code that you can use:<br />
[VB]<br />
Imports <strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Collections<br />
Imports <strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Lists<br />
Imports <strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Lists.Collections<br />
. . .<br />
Private Sub treeListView1_ItemDrag(ByVal sender As Object, ByVal e As<br />
ItemDragEventArgs)<br />
If e.Button = MouseButtons.Left Then<br />
Me.treeListView1.DoDragDrop(e.Item, DragDropEffects.All)<br />
End If<br />
End Sub<br />
47
Private Sub treeListView1_DragOver(ByVal sender As Object, ByVal e As<br />
DragEventArgs)<br />
If e.Data.GetDataPresent(GetType(<strong>TreeListView</strong>Item)) Then<br />
' Depending od the control key pressed change the drag effect<br />
If (e.KeyState And 8) = 8 AndAlso (e.AllowedEffect And DragDropEffects.Copy)<br />
= DragDropEffects.Copy Then<br />
e.Effect = DragDropEffects.Copy<br />
Else<br />
e.Effect = DragDropEffects.Move<br />
End If<br />
Else<br />
e.Effect = DragDropEffects.None<br />
End If<br />
End Sub<br />
Private Sub treeListView1_DragDrop(ByVal sender As Object, ByVal e As<br />
DragEventArgs)<br />
' Get the current mouse position<br />
Dim mousePos As Point = Me.treeListView1.PointToClient(New Point(e.X, e.Y))<br />
If<br />
e.Data.GetDataPresent(GetType(<strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Lists.<strong>TreeListView</strong>Node))<br />
Then<br />
' Get the dragged node<br />
Dim node As <strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Lists.<strong>TreeListView</strong>Node =<br />
DirectCast(e.Data.GetData(GetType(<strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Lists.<strong>TreeListView</strong>Node))<br />
, <strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Lists.<strong>TreeListView</strong>Node)<br />
' Get the target node (the one that is currently hovered)<br />
Dim targetNode As <strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Lists.<strong>TreeListView</strong>Node =<br />
Me.treeListView1.GetNodeAt(mousePos)<br />
' Suspend the treelistview layout to increase performance<br />
Me.treeListView1.SuspendUpdate()<br />
' In Copy operation, create a clone node and then add it to the target<br />
If e.Effect = DragDropEffects.Copy Then<br />
node = DirectCast(node.Clone(),<br />
<strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Lists.<strong>TreeListView</strong>Node)<br />
Else<br />
' Remove the node from its current parent node collection<br />
node.Remove()<br />
End If<br />
' If there is no target node, then add the dragged node at the end<br />
If targetNode Is Nothing Then<br />
Me.treeListView1.Nodes.Add(node)<br />
Else<br />
' Get the index of the dropped node in target <strong>TreeListView</strong> control<br />
Dim newIndex As Integer = Me.treeListView1.GetDropPos(targetNode,<br />
mousePos)<br />
If newIndex >= 0 Then<br />
If targetNode.Parent IsNot Nothing Then<br />
targetNode.Parent.Nodes.Insert(newIndex, node)<br />
Else<br />
Me.treeListView1.Nodes.Insert(newIndex, node)<br />
End If<br />
Else<br />
48
targetNode.Nodes.Add(node)<br />
End If<br />
End If<br />
' Resume the treelistview layout and update the control<br />
Me.treeListView1.ResumeUpdate()<br />
End If<br />
End Sub<br />
Private Sub treeListView1_QueryContinueDrag(ByVal sender As Object, ByVal e As<br />
QueryContinueDragEventArgs)<br />
Dim mousePos As Point = Me.treeListView1.PointToClient(Control.MousePosition)<br />
' Cancel the drag operation when the mouse cursor leaves the <strong>TreeListView</strong> space<br />
If Not Me.treeListView1.ClientRectangle.Contains(mousePos) Then<br />
e.Action = DragAction.Cancel<br />
End If<br />
End Sub<br />
[C#]<br />
using <strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Collections;<br />
using <strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Lists;<br />
using <strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Lists.Collections;<br />
. . .<br />
private void treeListView1_ItemDrag(object sender, ItemDragEventArgs e)<br />
{<br />
if (e.Button == MouseButtons.Left)<br />
this.treeListView1.DoDragDrop(e.Item, DragDropEffects.All);<br />
}<br />
private void treeListView1_DragOver(object sender, DragEventArgs e)<br />
{<br />
if<br />
(e.Data.GetDataPresent(typeof(<strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Lists.<strong>TreeListView</strong>Node)))<br />
{<br />
// Depending on the control key pressed change the drag effect<br />
if ((e.KeyState & 8) == 8 && (e.AllowedEffect & DragDropEffects.Copy) ==<br />
DragDropEffects.Copy)<br />
e.Effect = DragDropEffects.Copy;<br />
else<br />
e.Effect = DragDropEffects.Move;<br />
}<br />
else<br />
e.Effect = DragDropEffects.None;<br />
}<br />
private void treeListView1_DragDrop(object sender, DragEventArgs e)<br />
{<br />
// Get the current mouse position<br />
Point mousePos = this.treeListView1.PointToClient(new Point(e.X, e.Y));<br />
if<br />
(e.Data.GetDataPresent(typeof(<strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Lists.<strong>TreeListView</strong>Node)))<br />
{<br />
// Get the dragged node<br />
<strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Lists.<strong>TreeListView</strong>Node node =<br />
(<strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Lists.<strong>TreeListView</strong>Node)e.Data.GetData(typeof(<strong>Lidor</strong><strong>Systems</strong><br />
49
.<strong>IntegralUI</strong>.Lists.<strong>TreeListView</strong>Node));<br />
// Get the target node (the one that is currently hovered)<br />
<strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Lists.<strong>TreeListView</strong>Node targetNode =<br />
this.treeListView1.GetNodeAt(mousePos);<br />
// Suspend the treelistview layout to increase performance<br />
this.treeListView1.SuspendUpdate();<br />
// In Copy operation, create a clone node and then add it to the<br />
target<br />
if (e.Effect == DragDropEffects.Copy)<br />
node =<br />
(<strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Lists.<strong>TreeListView</strong>Node)node.Clone();<br />
// Remove the node from its current parent node collection<br />
else<br />
node.Remove();<br />
end<br />
control<br />
mousePos);<br />
}<br />
}<br />
// If there is no target node, then add the dragged node at the<br />
if (targetNode == null)<br />
this.treeListView1.Nodes.Add(node);<br />
else<br />
{<br />
// Get the index of the dropped node in target <strong>TreeListView</strong><br />
}<br />
int newIndex = this.treeListView1.GetDropPos(targetNode,<br />
if (newIndex >= 0)<br />
{<br />
if (targetNode.Parent != null)<br />
targetNode.Parent.Nodes.Insert(newIndex, node);<br />
else<br />
this.treeListView1.Nodes.Insert(newIndex, node);<br />
}<br />
else<br />
targetNode.Nodes.Add(node);<br />
// Resume the treelistview layout and update the control<br />
this.treeListView1.ResumeUpdate();<br />
private void treeListView1_QueryContinueDrag(object sender,<br />
QueryContinueDragEventArgs e)<br />
{<br />
Point mousePos = this.treeListView1.PointToClient(Control.MousePosition);<br />
// Cancel the drag operation when the mouse cursor leaves the <strong>TreeListView</strong><br />
space<br />
if (!this.treeListView1.ClientRectangle.Contains(mousePos))<br />
e.Action = DragAction.Cancel;<br />
}<br />
50
How to perform drag&drop for collection of nodes<br />
Instead of dragging a single node, you can also make dragging of collection of nodes. In the<br />
following example is presented how this can be accomplished for selected nodes:<br />
At first we need to set the SelectionMode to MultiSimple or MultiExtended.<br />
[VB]<br />
Imports <strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Lists<br />
. . .<br />
Private Sub treeListView1_ItemDrag(ByVal sender As Object, ByVal e As<br />
ItemDragEventArgs)<br />
If e.Button = MouseButtons.Left Then<br />
Dim nodeCollection As New<br />
<strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Lists.Collections.<strong>TreeListView</strong>NodeCollection()<br />
For Each node As <strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Lists.<strong>TreeListView</strong>Node In<br />
Me.treeListView1.SelectedNodes<br />
nodeCollection.Add(node)<br />
Next<br />
Me.treeListView1.DoDragDrop(nodeCollection, DragDropEffects.All)<br />
End If<br />
End Sub<br />
Private Sub treeListView1_DragOver(ByVal sender As Object, ByVal e As<br />
DragEventArgs)<br />
If<br />
e.Data.GetDataPresent(GetType(<strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Lists.Collections.TreeListVi<br />
ewNodeCollection)) Then<br />
' Depending od the control key pressed change the drag effect<br />
If (e.KeyState And 8) = 8 AndAlso (e.AllowedEffect And DragDropEffects.Copy)<br />
= DragDropEffects.Copy Then<br />
e.Effect = DragDropEffects.Copy<br />
Else<br />
e.Effect = DragDropEffects.Move<br />
End If<br />
Else<br />
e.Effect = DragDropEffects.None<br />
End If<br />
End Sub<br />
Private Sub treeListView1_DragDrop(ByVal sender As Object, ByVal e As<br />
DragEventArgs)<br />
' Get the current mouse position<br />
Dim mousePos As Point = Me.treeListView1.ContentPanel.PointToClient(New<br />
Point(e.X, e.Y))<br />
If<br />
e.Data.GetDataPresent(GetType(<strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Lists.Collections.TreeListVi<br />
ewNodeCollection)) Then<br />
' Get the dragged node collection<br />
Dim nodeCollection As<br />
<strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Lists.Collections.<strong>TreeListView</strong>NodeCollection =<br />
DirectCast(e.Data.GetData(GetType(<strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Lists.Collections.TreeLi<br />
stViewNodeCollection)),<br />
<strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Lists.Collections.<strong>TreeListView</strong>NodeCollection)<br />
51
' Get the target node (the one that is currently hovered)<br />
Dim targetNode As <strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Lists.<strong>TreeListView</strong>Node =<br />
Me.treeListView1.GetNodeAt(mousePos)<br />
' Suspend the treelistview layout to increase performance<br />
Me.treeListView1.SuspendUpdate()<br />
' Get the collection at which nodes will be added<br />
If targetNode Is Nothing Then<br />
' In Copy operation, create a clone node and then add it to the target<br />
If e.Effect = DragDropEffects.Copy Then<br />
For Each node As <strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Lists.<strong>TreeListView</strong>Node In<br />
nodeCollection<br />
Me.treeListView1.Nodes.Add(node.Clone())<br />
Next<br />
' In Move operation, it's best to use the while cycle, because when<br />
moving existing node<br />
' it will alter the source node collection which can cause errors.<br />
' The best approach is the code bellow.<br />
ElseIf e.Effect = DragDropEffects.Move Then<br />
For Each node As <strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Lists.<strong>TreeListView</strong>Node In<br />
nodeCollection<br />
node.Remove()<br />
' Add the node to the <strong>TreeListView</strong><br />
Me.treeListView1.Nodes.Add(node)<br />
Next<br />
End If<br />
Else<br />
' Get the index of the dropped node in target <strong>TreeListView</strong> control<br />
Dim newIndex As Integer = Me.treeListView1.GetDropPos(targetNode,<br />
mousePos)<br />
' In Copy operation, create a clone node and then add it to the target<br />
If e.Effect = DragDropEffects.Copy Then<br />
For Each node As <strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Lists.<strong>TreeListView</strong>Node In<br />
nodeCollection<br />
If newIndex >= 0 Then<br />
If targetNode.Parent IsNot Nothing Then<br />
targetNode.Parent.Nodes.Insert(newIndex, node.Clone())<br />
Else<br />
Me.treeListView1.Nodes.Insert(newIndex, node.Clone())<br />
End If<br />
Else<br />
targetNode.Nodes.Add(node.Clone())<br />
End If<br />
Next<br />
' In Move operation, it's best to use the while cycle, because when<br />
moving existing node<br />
' it will alter the source node collection which can cause errors.<br />
' The best approach is the node bellow.<br />
ElseIf e.Effect = DragDropEffects.Move Then<br />
For Each node As <strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Lists.<strong>TreeListView</strong>Node In<br />
nodeCollection<br />
node.Remove()<br />
' Place the node at correct position<br />
If newIndex >= 0 Then<br />
If targetNode.Parent IsNot Nothing Then<br />
52
targetNode.Parent.Nodes.Insert(newIndex, node)<br />
Else<br />
Me.treeListView1.Nodes.Insert(newIndex, node)<br />
End If<br />
Else<br />
targetNode.Nodes.Add(node)<br />
End If<br />
Next<br />
End If<br />
End If<br />
' Resume the treelistview layout and update the control<br />
Me.treeListView1.ResumeUpdate()<br />
End If<br />
End Sub<br />
[C#]<br />
using <strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Lists;<br />
. . .<br />
private void treeListView1_ItemDrag(object sender, ItemDragEventArgs e)<br />
{<br />
if (e.Button == MouseButtons.Left)<br />
{<br />
<strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Lists.Collections.<strong>TreeListView</strong>NodeCollection<br />
nodeCollection = new<br />
<strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Lists.Collections.<strong>TreeListView</strong>NodeCollection();<br />
foreach (<strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Lists.<strong>TreeListView</strong>Node node in<br />
this.treeListView1.SelectedNodes)<br />
nodeCollection.Add(node);<br />
}<br />
}<br />
this.treeListView1.DoDragDrop(nodeCollection, DragDropEffects.All);<br />
private void treeListView1_DragOver(object sender, DragEventArgs e)<br />
{<br />
if<br />
(e.Data.GetDataPresent(typeof(<strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Lists.Collections.TreeListVi<br />
ewNodeCollection)))<br />
{<br />
// Depending od the control key pressed change the drag effect<br />
if ((e.KeyState & 8) == 8 && (e.AllowedEffect & DragDropEffects.Copy) ==<br />
DragDropEffects.Copy)<br />
e.Effect = DragDropEffects.Copy;<br />
else<br />
e.Effect = DragDropEffects.Move;<br />
}<br />
else<br />
e.Effect = DragDropEffects.None;<br />
}<br />
private void treeListView1_DragDrop(object sender, DragEventArgs e)<br />
{<br />
// Get the current mouse position<br />
Point mousePos = this.treeListView1.ContentPanel.PointToClient(new Point(e.X,<br />
e.Y));<br />
53
if<br />
(e.Data.GetDataPresent(typeof(<strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Lists.Collections.TreeListVi<br />
ewNodeCollection)))<br />
{<br />
// Get the dragged node collection<br />
<strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Lists.Collections.<strong>TreeListView</strong>NodeCollection<br />
nodeCollection =<br />
(<strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Lists.Collections.<strong>TreeListView</strong>NodeCollection)e.Data.GetDa<br />
ta(typeof(<strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Lists.Collections.<strong>TreeListView</strong>NodeCollection));<br />
// Get the target node (the one that is currently hovered)<br />
<strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Lists.<strong>TreeListView</strong>Node targetNode =<br />
this.treeListView1.GetNodeAt(mousePos);<br />
// Suspend the treelistview layout to increase performance<br />
this.treeListView1.SuspendUpdate();<br />
// Get the collection at which nodes will be added<br />
if (targetNode == null)<br />
{<br />
// In Copy operation, create a clone node and then add it to the target<br />
if (e.Effect == DragDropEffects.Copy)<br />
{<br />
foreach (<strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Lists.<strong>TreeListView</strong>Node node in<br />
nodeCollection)<br />
this.treeListView1.Nodes.Add(node.Clone());<br />
}<br />
// In Move operation, it's best to use the while cycle, because when<br />
moving existing node<br />
// it will alter the source node collection which can cause errors.<br />
// The best approach is the code bellow.<br />
else if (e.Effect == DragDropEffects.Move)<br />
{<br />
foreach (<strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Lists.<strong>TreeListView</strong>Node node in<br />
nodeCollection)<br />
{<br />
node.Remove();<br />
// Add the node to the <strong>TreeListView</strong><br />
this.treeListView1.Nodes.Add(node);<br />
}<br />
}<br />
}<br />
else<br />
{<br />
// Get the index of the dropped node in target <strong>TreeListView</strong> control<br />
int newIndex = this.treeListView1.GetDropPos(targetNode, mousePos);<br />
// In Copy operation, create a clone node and then add it to the target<br />
if (e.Effect == DragDropEffects.Copy)<br />
{<br />
foreach (<strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Lists.<strong>TreeListView</strong>Node node in<br />
nodeCollection)<br />
{<br />
if (newIndex >= 0)<br />
{<br />
if (targetNode.Parent != null)<br />
targetNode.Parent.Nodes.Insert(newIndex, node.Clone());<br />
else<br />
54
this.treeListView1.Nodes.Insert(newIndex, node.Clone());<br />
}<br />
else<br />
targetNode.Nodes.Add(node.Clone());<br />
}<br />
}<br />
// In Move operation, it's best to use the while cycle, because when<br />
moving existing node<br />
// it will alter the source node collection which can cause errors.<br />
// The best approach is the node bellow.<br />
else if (e.Effect == DragDropEffects.Move)<br />
{<br />
foreach (<strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Lists.<strong>TreeListView</strong>Node node in<br />
nodeCollection)<br />
{<br />
node.Remove();<br />
}<br />
}<br />
}<br />
}<br />
}<br />
// Place the node at correct position<br />
if (newIndex >= 0)<br />
{<br />
if (targetNode.Parent != null)<br />
targetNode.Parent.Nodes.Insert(newIndex, node);<br />
else<br />
this.treeListView1.Nodes.Insert(newIndex, node);<br />
}<br />
else<br />
targetNode.Nodes.Add(node);<br />
// Resume the treelistview layout and update the control<br />
this.treeListView1.ResumeUpdate();<br />
How to perform drag&drop of a node to other controls<br />
Other controls can accept nodes during drag&drop operation, if their AllowDrop property is set to<br />
True. In the following example we will demonstrate how node dragged from the <strong>TreeListView</strong><br />
control can be dropped in TextBox control:<br />
[VB]<br />
Private Sub textBox1_DragOver(ByVal sender As Object, ByVal e As DragEventArgs)<br />
If<br />
e.Data.GetDataPresent(GetType(<strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Lists.<strong>TreeListView</strong>Node))<br />
Then<br />
e.Effect = DragDropEffects.Move<br />
Else<br />
e.Effect = DragDropEffects.None<br />
End If<br />
End Sub<br />
Private Sub textBox1_DragDrop(ByVal sender As Object, ByVal e As DragEventArgs)<br />
If<br />
e.Data.GetDataPresent(GetType(<strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Lists.<strong>TreeListView</strong>Node))<br />
Then<br />
' Get the dragged node<br />
55
Dim node As <strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Lists.<strong>TreeListView</strong>Node =<br />
DirectCast(e.Data.GetData(GetType(<strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Lists.<strong>TreeListView</strong>Node))<br />
, <strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Lists.<strong>TreeListView</strong>Node)<br />
' Set the Text property of TextBox control to contain the node text<br />
Me.textBox1.Text = node.Text<br />
End If<br />
End Sub<br />
[C#]<br />
private void textBox1_DragOver(object sender, DragEventArgs e)<br />
{<br />
if<br />
(e.Data.GetDataPresent(typeof(<strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Lists.<strong>TreeListView</strong>Node)))<br />
e.Effect = DragDropEffects.Move;<br />
else<br />
e.Effect = DragDropEffects.None;<br />
}<br />
private void textBox1_DragDrop(object sender, DragEventArgs e)<br />
{<br />
if<br />
(e.Data.GetDataPresent(typeof(<strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Lists.<strong>TreeListView</strong>Node)))<br />
{<br />
// Get the dragged node<br />
<strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Lists.<strong>TreeListView</strong>Node node =<br />
(<strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Lists.<strong>TreeListView</strong>Node)e.Data.GetData(typeof(<strong>Lidor</strong><strong>Systems</strong><br />
.<strong>IntegralUI</strong>.Lists.<strong>TreeListView</strong>Node));<br />
}<br />
}<br />
Sorting<br />
// Set the Text property of TextBox control to contain the node text<br />
this.textBox1.Text = node.Text;<br />
When you have large list of nodes, the best to search through them is if they are sorted. The<br />
<strong>TreeListView</strong> control supports predefined sorting of nodes based on some predefined types. Also,<br />
you can customize the sorting by creating your own implementation of IComparer interface.<br />
Typically nodes are sorted using the Sorting property, which can have three values: None,<br />
Ascending and Descending. By default, the Sorting property has value None, which means that<br />
automatically sorting of nodes is disabled.<br />
Use of predefined sorting method<br />
When the Sorting property is set to other value then None, automatically sorting is active. So<br />
whenever a new node is added or removed, the list will be sorted. The nodes will be sorted<br />
depending of current value of ComparerObjectType, which can have one of these values:<br />
• Double<br />
• Integer<br />
• String<br />
Additionally, the sorting will only work for those nodes or subitems that have their SortTag set to<br />
some value. Nodes with their SortTag set to null, will be excluded from sorting.<br />
56
In the following example the nodes will be sorted by their Integer value from the largest to lowest<br />
number:<br />
[VB]<br />
' At first set the SortTag for each node to some Integer value<br />
For i As Integer = 0 To Me.treeListView1.FlatNodes.Count - 1<br />
Me.treeListView1.FlatNodes(i).SortTag = i<br />
Next<br />
' Change the ComparerObjectType to Integer, so the sorting will be used comparing<br />
Integer values<br />
Me.treeListView1.ComparerObjectType =<br />
<strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Lists.ComparerObjectType.Integer<br />
' Arrange nodes and subnodes from largest to lowest number<br />
Me.treeListView1.Sorting = SortOrder.Descending<br />
[C#]<br />
// At first set the SortTag for each node to some Integer value<br />
for (int i = 0; i < this.treeListView1.FlatNodes.Count; i++)<br />
this.treeListView1.FlatNodes[i].SortTag = i;<br />
// Change the ComparerObjectType to Integer, so the sorting will be used<br />
comparing Integer values<br />
this.treeListView1.ComparerObjectType =<br />
<strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Lists.ComparerObjectType.Integer;<br />
// Arrange nodes and subnodes from largest to lowest number<br />
this.treeListView1.Sorting = SortOrder.Descending;<br />
If you want to sort the nodes by specified column, then the corresponding subitems must have set<br />
their SortTag property to specific value. Thouse subitems with their SortTag set to null will be<br />
excluded from sorting. Here is an example where nodes are sorted by clicking on the second<br />
column:<br />
[VB]<br />
Imports <strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Lists<br />
. . .<br />
' Fill the subitems from the second column with data used for sorting<br />
Private Sub InitSortList(ByVal sender As Object, ByVal e As EventArgs)<br />
' At first set the SortTag for each subitem in second column to some Integer<br />
value<br />
For i As Integer = 0 To Me.treeListView1.FlatNodes.Count - 1<br />
If Me.treeListView1.FlatNodes(i).SubItems.Count > 1 Then<br />
Me.treeListView1.FlatNodes(i).SubItems(1).SortTag = i<br />
End If<br />
Next<br />
' Change the ComparerObjectType to Integer, so the sorting will be used<br />
comparing Integer values<br />
Me.treeListView1.ComparerObjectType =<br />
<strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Lists.ComparerObjectType.[Integer]<br />
End Sub<br />
' Handle the ColumnClick event to start sort operation<br />
57
Private Sub treeListView1_ColumnClick(ByVal sender As Object, ByVal e As<br />
<strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.ObjectClickEventArgs)<br />
If TypeOf e.[Object] Is <strong>TreeListView</strong>Column Then<br />
Dim column As <strong>TreeListView</strong>Column = DirectCast(e.[Object],<br />
<strong>TreeListView</strong>Column)<br />
' Start the Sort operation only when second column is clicked<br />
If column.Index = 1 Then<br />
Select Case Me.treeListView1.Sorting<br />
Case SortOrder.Ascending<br />
Me.treeListView1.Sorting = SortOrder.Descending<br />
Exit Select<br />
Case SortOrder.Descending<br />
Me.treeListView1.Sorting = SortOrder.Ascending<br />
Exit Select<br />
Case Else<br />
Me.treeListView1.Sorting = SortOrder.Descending<br />
Exit Select<br />
End Select<br />
End If<br />
End If<br />
End Sub<br />
[C#]<br />
using <strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Lists;<br />
. . .<br />
// Fill the subitems from the second column with data used for sorting<br />
private void InitSortList(object sender, EventArgs e)<br />
{<br />
// At first set the SortTag for each subitem in second column to some Integer<br />
value<br />
for (int i = 0; i < this.treeListView1.FlatNodes.Count; i++)<br />
{<br />
if (this.treeListView1.FlatNodes[i].SubItems.Count > 1)<br />
this.treeListView1.FlatNodes[i].SubItems[1].SortTag = i;<br />
}<br />
// Change the ComparerObjectType to Integer, so the sorting will be used<br />
comparing Integer values<br />
this.treeListView1.ComparerObjectType =<br />
<strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Lists.ComparerObjectType.Integer;<br />
}<br />
// Handle the ColumnClick event to start sort operation<br />
private void treeListView1_ColumnClick(object sender,<br />
<strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.ObjectClickEventArgs e)<br />
{<br />
if (e.Object is <strong>TreeListView</strong>Column)<br />
{<br />
<strong>TreeListView</strong>Column column = (<strong>TreeListView</strong>Column)e.Object;<br />
// Start the Sort operation only when second column is clicked<br />
if (column.Index == 1)<br />
{<br />
switch (this.treeListView1.Sorting)<br />
58
}<br />
}<br />
}<br />
{<br />
}<br />
Create custom sorting<br />
case SortOrder.Ascending:<br />
this.treeListView1.Sorting = SortOrder.Descending;<br />
break;<br />
case SortOrder.Descending:<br />
this.treeListView1.Sorting = SortOrder.Ascending;<br />
break;<br />
default:<br />
this.treeListView1.Sorting = SortOrder.Descending;<br />
break;<br />
To customize the sort order, you must write a class that implements the IComparer interface and<br />
set the ListItemSorter property to an object of that class. This is useful, for example, when you<br />
want to sort nodes by DateTime value added to the subitem Tag property.<br />
Here is an example of custom sort operation. At first initialize the sort data:<br />
[VB]<br />
Imports <strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Lists<br />
. . .<br />
Private Sub InitSortList(ByVal sender As Object, ByVal e As EventArgs)<br />
Dim sampleDate As New DateTime(2008, 1, 1)<br />
' At first set the Tag for each subitem in second column to some random<br />
date<br />
For i As Integer = 0 To Me.treeListView1.FlatNodes.Count - 1<br />
If Me.treeListView1.FlatNodes(i).SubItems.Count > 1 Then<br />
sampleDate = CreateRandomDate(sampleDate)<br />
Me.treeListView1.FlatNodes(i).SubItems(1).Text =<br />
sampleDate.ToShortDateString()<br />
Me.treeListView1.FlatNodes(i).SubItems(1).Tag = sampleDate<br />
End If<br />
Next<br />
End Sub<br />
' Use this method to create random dates<br />
Private Function CreateRandomDate(ByVal value As DateTime) As DateTime<br />
Dim gen As New Random()<br />
Dim range As Integer = DirectCast((DateTime.Today - value),<br />
TimeSpan).Days<br />
Return value.AddDays(gen.[Next](range))<br />
End Function<br />
[C#]<br />
using <strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Lists;<br />
. . .<br />
59
private void InitSortList(object sender, EventArgs e)<br />
{<br />
DateTime sampleDate = new DateTime(2008, 1, 1);<br />
// At first set the Tag for each subitem in second column to some random date<br />
for (int i = 0; i < this.treeListView1.FlatNodes.Count; i++)<br />
{<br />
if (this.treeListView1.FlatNodes[i].SubItems.Count > 1)<br />
{<br />
sampleDate = CreateRandomDate(sampleDate);<br />
this.treeListView1.FlatNodes[i].SubItems[1].Text =<br />
sampleDate.ToShortDateString();<br />
this.treeListView1.FlatNodes[i].SubItems[1].Tag = sampleDate;<br />
}<br />
}<br />
}<br />
// Use this method to create random dates<br />
private DateTime CreateRandomDate(DateTime value)<br />
{<br />
Random gen = new Random();<br />
int range = ((TimeSpan)(DateTime.Today - value)).Days;<br />
return value.AddDays(gen.Next(range));<br />
}<br />
Then create a new class that implements the IComparer interface:<br />
[VB]<br />
Public Class CustomItemComparer<br />
Implements System.Collections.IComparer<br />
Private sortType As System.Windows.Forms.SortOrder =<br />
System.Windows.Forms.SortOrder.Ascending<br />
Private col As Integer = -1<br />
Public Sub New()<br />
End Sub<br />
Public Sub New(ByVal order As System.Windows.Forms.SortOrder, ByVal<br />
colIndex As Integer)<br />
sortType = order<br />
col = colIndex<br />
End Sub<br />
Public Function Compare(ByVal x As Object, ByVal y As Object) As Integer<br />
If sortType = System.Windows.Forms.SortOrder.Descending Then<br />
Dim temp As Object = x<br />
x = y<br />
y = temp<br />
End If<br />
Dim firstDate As Object = Nothing<br />
Dim secondDate As Object = Nothing<br />
If col >= 0 Then<br />
If col < TryCast(x, <strong>TreeListView</strong>Node).SubItems.Count Then<br />
firstDate = TryCast(x, <strong>TreeListView</strong>Node).SubItems(col).Tag<br />
End If<br />
60
If col < TryCast(y, <strong>TreeListView</strong>Node).SubItems.Count Then<br />
secondDate = TryCast(y, <strong>TreeListView</strong>Node).SubItems(col).Tag<br />
End If<br />
End If<br />
If firstDate IsNot Nothing AndAlso secondDate IsNot Nothing Then<br />
If firstDate.[GetType]() Is GetType(DateTime) AndAlso secondDate.<br />
[GetType]() Is GetType(DateTime) Then<br />
Return DateTime.Compare(DirectCast(firstDate, DateTime),<br />
DirectCast(secondDate, DateTime))<br />
End If<br />
End If<br />
Return 0<br />
End Function<br />
End Class<br />
[C#]<br />
public class CustomItemComparer : System.Collections.IComparer<br />
{<br />
private System.Windows.Forms.SortOrder sortType =<br />
System.Windows.Forms.SortOrder.Ascending;<br />
private int col = -1;<br />
public CustomItemComparer()<br />
{<br />
}<br />
public CustomItemComparer(System.Windows.Forms.SortOrder order, int colIndex)<br />
{<br />
sortType = order;<br />
col = colIndex;<br />
}<br />
public int Compare(object x, object y)<br />
{<br />
if (sortType == System.Windows.Forms.SortOrder.Descending)<br />
{<br />
object temp = x;<br />
x = y;<br />
y = temp;<br />
}<br />
object firstDate = null;<br />
object secondDate = null;<br />
if (col >= 0)<br />
{<br />
if (col < (x as <strong>TreeListView</strong>Node).SubItems.Count)<br />
firstDate = (x as <strong>TreeListView</strong>Node).SubItems[col].Tag;<br />
}<br />
if (col < (y as <strong>TreeListView</strong>Node).SubItems.Count)<br />
secondDate = (y as <strong>TreeListView</strong>Node).SubItems[col].Tag;<br />
if (firstDate != null && secondDate != null)<br />
{<br />
if (firstDate.GetType() == typeof(DateTime) && secondDate.GetType() ==<br />
typeof(DateTime))<br />
61
}<br />
}<br />
}<br />
return 0;<br />
return DateTime.Compare((DateTime)firstDate, (DateTime)secondDate);<br />
At the end, add an object from this class to the ListItemSorter property:<br />
[VB]<br />
Private Sub treeListView1_ColumnClick(ByVal sender As Object, ByVal e As<br />
<strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.ObjectClickEventArgs)<br />
If TypeOf e.[Object] Is <strong>TreeListView</strong>Column Then<br />
Dim column As <strong>TreeListView</strong>Column = DirectCast(e.[Object],<br />
<strong>TreeListView</strong>Column)<br />
If column.Index = 1 Then<br />
Select Case Me.treeListView1.Sorting<br />
Case SortOrder.Ascending<br />
Me.treeListView1.Sorting = SortOrder.Descending<br />
Exit Select<br />
Case SortOrder.Descending<br />
Me.treeListView1.Sorting = SortOrder.Ascending<br />
Exit Select<br />
Case Else<br />
Me.treeListView1.Sorting = SortOrder.Descending<br />
Exit Select<br />
End Select<br />
Me.treeListView1.ListItemSorter = New<br />
CustomItemComparer(Me.treeListView1.Sorting, column.Index)<br />
End If<br />
End If<br />
End Sub<br />
[C#]<br />
// Handle the ColumnClick event to start sort operation<br />
private void treeListView1_ColumnClick(object sender,<br />
<strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.ObjectClickEventArgs e)<br />
{<br />
if (e.Object is <strong>TreeListView</strong>Column)<br />
{<br />
<strong>TreeListView</strong>Column column = (<strong>TreeListView</strong>Column)e.Object;<br />
// Start the Sort operation only when second column is clicked<br />
if (column.Index == 1)<br />
{<br />
switch (this.treeListView1.Sorting)<br />
{<br />
case SortOrder.Ascending:<br />
this.treeListView1.Sorting = SortOrder.Descending;<br />
break;<br />
case SortOrder.Descending:<br />
this.treeListView1.Sorting = SortOrder.Ascending;<br />
break;<br />
62
}<br />
default:<br />
this.treeListView1.Sorting = SortOrder.Descending;<br />
break;<br />
// Apply the custom sort operation<br />
this.treeListView1.ListItemSorter = new<br />
CustomItemComparer(this.treeListView1.Sorting, column.Index);<br />
}<br />
}<br />
}<br />
Search<br />
How to find a node by using specific criteria<br />
If you want to find a node with specific value, the best is to use the FindNode method. The search<br />
criteria can be byKey, byPath or byTagString. Here is an example:<br />
[VB]<br />
Dim node As <strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Lists.<strong>TreeListView</strong>Node =<br />
Me.treeListView1.FindNode ("ITM",<br />
<strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Lists.ListSearchCriteria.byKey)<br />
[C#]<br />
<strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Lists.<strong>TreeListView</strong>Node node =<br />
this.treeListView1.FindNode("ITM",<br />
<strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Lists.ListSearchCriteria.byKey);<br />
The method will search through nodes, and compare their Key property value to match the “ITM”<br />
value. If some node is found it will return their reference, otherwise a null will be returned.<br />
How to get a node reference from mouse position<br />
Sometimes, while hovering inside the <strong>TreeListView</strong> control client area, you may want to know<br />
which node the actual mouse cursor points at. To receive the node reference, you need to use the<br />
GetNodeAt method, here is how:<br />
[VB]<br />
' Convert the screen coordinates of the mouse cursor position to client<br />
coordinates of the <strong>TreeListView</strong> control<br />
Dim mousePos As Point =<br />
Me.treeListView1.ContentPanel.PointToClient(Control.MousePosition)<br />
' Get the node reference (if there is any), at the specified position<br />
Dim node As <strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Lists.<strong>TreeListView</strong>Node =<br />
Me.treeListView1.GetNodeAt(mousePos)<br />
[C#]<br />
// Convert the screen coordinates of the mouse cursor position to client<br />
coordinates of the <strong>TreeListView</strong> control<br />
Point mousePos =<br />
this.treeListView1.ContentPanel.PointToClient(Control.MousePosition);<br />
// Get the node reference (if there is any), at the specified position<br />
63
<strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Lists.<strong>TreeListView</strong>Node node =<br />
this.treeListView1.GetNodeAt(mousePos);<br />
You can also use the GetHoverNode method:<br />
[VB]<br />
Dim node As <strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Lists.<strong>TreeListView</strong>Node =<br />
Me.treeListView1.GetHoverNode()<br />
[C#]<br />
<strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Lists.<strong>TreeListView</strong>Node node =<br />
this.treeListView1.GetHoverNode();<br />
Keyword search<br />
There is a built-in search operations by pressing keys. For this behavior, the KeySearchMode<br />
property is used with following values:<br />
• None – The search is disabled.<br />
• Partial – The search is started whenever there is a key(s) pressed.<br />
• Full – The same as Partial search, only this time the subitems are also included in<br />
searching.<br />
The search process begins whenever there is a single key pressed or a string with multiple<br />
characters in it. The search begins always from index 0. For example: whenever the ‘A’ key is<br />
pressed, the search is started. Also if you pressed keys in following order ‘ABC’ the search is also<br />
started. However, you must press the consecutive keys in time less then 500 miliseconds<br />
between each pressed key. This is enough time to enter a search string with large length. If the<br />
node is found it is selected and positioned to the center of control visible area.<br />
You can also manually search for nodes, by using FindNode methods. Here is how:<br />
1. Set the KeySearchMode to None<br />
2. Handle the KeyDown event or use some other way to start the search (like Button click<br />
event)<br />
3. Use the FindNode methods<br />
[VB]<br />
Private Sub treeListView1_KeyDown(ByVal sender As Object, ByVal e As<br />
KeyEventArgs)<br />
' Search for an node with matching Text starting from index 0.<br />
' Subitems are also included in searching<br />
Dim node As <strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Lists.<strong>TreeListView</strong>Node =<br />
Me.treeListView1.FindNode(GetAlphaNumValue(e.KeyCode), true, 0, true)<br />
If node IsNot Nothing Then<br />
' Select the found node<br />
Me.treeListView1.SelectedNode = node<br />
If Me.treeListView1.IsVScrollVisible() Then<br />
' If the node is not in visible area, set the scrollbar position to show<br />
' the found node in center of ListView control<br />
If node.Bounds.Y ><br />
64
Me.treeListView1.ContentPanel.ClientRectangle.Height / 2 Then<br />
Me.treeListView1.SetScrollPos(New Point(0, node.Bounds.Y -<br />
Me.treeListView1.ContentPanel.ClientRectangle.Height / 2))<br />
Else<br />
Me.treeListView1.SetScrollPos(New Point(0, node.Bounds.Y -<br />
node.Bounds.Height))<br />
End If<br />
End If<br />
End If<br />
End Sub<br />
Protected Overridable Function GetAlphaNumValue(ByVal keyData As Keys) As String<br />
Select Case keyData<br />
Case Keys.A, Keys.B, Keys.C, Keys.D, Keys.E, Keys.F, _<br />
Keys.G, Keys.H, Keys.I, Keys.J, Keys.K, Keys.L, _<br />
Keys.M, Keys.N, Keys.O, Keys.P, Keys.Q, Keys.R, _<br />
Keys.S, Keys.T, Keys.U, Keys.V, Keys.W, Keys.X, _<br />
Keys.Y, Keys.Z<br />
Return keyData.ToString()<br />
Case Keys.D0, Keys.NumPad0<br />
Return "0"<br />
Case Keys.D1, Keys.NumPad1<br />
Return "1"<br />
Case Keys.D2, Keys.NumPad2<br />
Return "2"<br />
Case Keys.D3, Keys.NumPad3<br />
Return "3"<br />
Case Keys.D4, Keys.NumPad4<br />
Return "4"<br />
Case Keys.D5, Keys.NumPad5<br />
Return "5"<br />
Case Keys.D6, Keys.NumPad6<br />
Return "6"<br />
Case Keys.D7, Keys.NumPad7<br />
Return "7"<br />
Case Keys.D8, Keys.NumPad8<br />
Return "8"<br />
Case Keys.D9, Keys.NumPad9<br />
Return "9"<br />
Case Keys.Space<br />
Return " "<br />
End Select<br />
Return String.Empty<br />
End Function<br />
[C#]<br />
private void treeListView1_KeyDown(object sender, KeyEventArgs e)<br />
65
{<br />
// Search for an node with matching Text starting from index 0.<br />
// Subitems are also included in searching<br />
<strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Lists.<strong>TreeListView</strong>Node node =<br />
this.treeListView1.FindNode(GetAlphaNumValue(e.KeyCode), true, 0, true);<br />
show<br />
if (node != null)<br />
{<br />
// Select the found node<br />
this.treeListView1.SelectedNode = node;<br />
if (this.treeListView1.IsVScrollVisible())<br />
{<br />
// If the node is not in visible area, set the scrollbar position to<br />
// the found node in center of ListView control<br />
if (node.Bounds.Y ><br />
this.treeListView1.ContentPanel.ClientRectangle.Height / 2)<br />
this.treeListView1.SetScrollPos(new Point(0, node.Bounds.Y -<br />
this.treeListView1.ContentPanel.ClientRectangle.Height / 2));<br />
else<br />
this.treeListView1.SetScrollPos(new Point(0, node.Bounds.Y -<br />
node.Bounds.Height));<br />
}<br />
}<br />
}<br />
protected virtual string GetAlphaNumValue(Keys keyData)<br />
{<br />
switch (keyData)<br />
{<br />
case Keys.A:<br />
case Keys.B:<br />
case Keys.C:<br />
case Keys.D:<br />
case Keys.E:<br />
case Keys.F:<br />
case Keys.G:<br />
case Keys.H:<br />
case Keys.I:<br />
case Keys.J:<br />
case Keys.K:<br />
case Keys.L:<br />
case Keys.M:<br />
case Keys.N:<br />
case Keys.O:<br />
case Keys.P:<br />
case Keys.Q:<br />
case Keys.R:<br />
case Keys.S:<br />
case Keys.T:<br />
case Keys.U:<br />
case Keys.V:<br />
case Keys.W:<br />
case Keys.X:<br />
case Keys.Y:<br />
case Keys.Z:<br />
return keyData.ToString();<br />
66
}<br />
}<br />
case Keys.D0:<br />
case Keys.NumPad0:<br />
return "0";<br />
case Keys.D1:<br />
case Keys.NumPad1:<br />
return "1";<br />
case Keys.D2:<br />
case Keys.NumPad2:<br />
return "2";<br />
case Keys.D3:<br />
case Keys.NumPad3:<br />
return "3";<br />
case Keys.D4:<br />
case Keys.NumPad4:<br />
return "4";<br />
case Keys.D5:<br />
case Keys.NumPad5:<br />
return "5";<br />
case Keys.D6:<br />
case Keys.NumPad6:<br />
return "6";<br />
case Keys.D7:<br />
case Keys.NumPad7:<br />
return "7";<br />
case Keys.D8:<br />
case Keys.NumPad8:<br />
return "8";<br />
case Keys.D9:<br />
case Keys.NumPad9:<br />
return "9";<br />
case Keys.Space:<br />
return " ";<br />
return String.Empty;<br />
How to maintain scroll position<br />
In order to manually change the position of scrollbar, there are two methods for this purpose:<br />
• GetScrollPos – returns the current position of vertical and horizontal scrollbar<br />
• SetScrollPos – sets the position of vertical and horizontal scrollbar to a specified value<br />
Every node has Bounds property which holds the area in which the node content is drawn. This<br />
property has their position in absolute coordinates related to the origin of the control client area.<br />
So, if you want to have some specific node placed at the top of visible area, you can do that by<br />
using this code:<br />
67
[VB]<br />
Me.treeListView1.SetScrollPos(New Point(0, node.Bounds.Y))<br />
[C#]<br />
this.treeListView1.SetScrollPos(new Point(0, node.Bounds.Y));<br />
The Top position of the node is directly related to the position of vertical scrollbar.<br />
68
XML Encoding<br />
By default the <strong>TreeListView</strong> shows nodes ordered in simplified way, a hierarchical structure where<br />
each node contains image and a label. This is not much useful when you want to present your<br />
data in more custom layout.<br />
By using XML tags you can create various different templates which will contain custom objects<br />
placed in custom location in column, node or subitem space. These custom objects represents:<br />
text, images, custom controls, hyperlinks, animated gifs etc. There are a set of XML tags with<br />
which you can design the layouts. These templates can be applied to all columns, nodes or<br />
subitems (to keep their uniform look), or are free to create separate templates.<br />
The result is a very rich and customizable presentation of your data.<br />
XML Tags that are supported<br />
The use of XML tags is very like the using of standard HTML tags. In the following section the list<br />
of supported XML tags is presented in alphabetical order:<br />
Tag Atribute Description<br />
<br />
Defines an anchor with which you can create a link to another<br />
document<br />
href The target URL of the link<br />
id The identifier of the hyperlink<br />
style An inline style definition<br />
underlined<br />
The text is rendered as bold<br />
Determines whether the link text is underlined. Default value is<br />
true.<br />
id The identifier of the text enclosed with this tag<br />
style An inline style definition<br />
inserts a single line break<br />
Defines a custom control<br />
height Sets the height of a control<br />
index Specifies the position of the control in a collection<br />
style An inline style definition<br />
width Sets the width of a control<br />
Defines the main section of the content<br />
style An inline style definition<br />
specifies the font of text<br />
color Defines the color of the text<br />
face Defines the font name of the text<br />
id The identifier of the text enclosed with this tag<br />
size Defines the size of the text<br />
style An inline style definition<br />
69
The text is rendered as italic<br />
id The identifier of the text enclosed with this tag<br />
style An inline style definition<br />
Defines an image<br />
assemblypath Specifies the path of an assembly used as a resource file<br />
height Sets the height of an image<br />
id The identifier of the image<br />
index Specifies the position of the image in a collection<br />
resource The resource object to be retrieved from assembly<br />
src The URL of the image to display<br />
style An inline style definition<br />
width Sets the width of an image<br />
Defines a new section (paragraph) in the content<br />
indent<br />
Specifies a space (in pixels) by which paragraph’s content is<br />
moved to the right<br />
style An inline style definition<br />
defines a table<br />
cellpadding Specifies the space between the table cell border and content<br />
cellspacing Specifies the space between table cells<br />
style An inline style definition<br />
width Specifies the width of the table. Can be specified in % or pixels.<br />
Defines a cell in a table<br />
align Specifies the horizontal alignment of cell content<br />
colspan Indicates the number of columns this cell should span<br />
height<br />
Specifies the height of the table cell. Can be specified in % or<br />
pixels.<br />
rowspan Indicates the number of rows this cell should span<br />
style An inline style definition<br />
valign Specifies the vertical alignment of cell content<br />
width<br />
Specifies the width of the table cell. Can be specified in % or<br />
pixels.<br />
Defines a new section (paragraph) in the content<br />
align Specifies the horizontal alignment of cell content<br />
height<br />
Specifies the height of the table row. Can be specified in % or<br />
pixels.<br />
style An inline style definition<br />
valign Specifies the vertical alignment of cell content<br />
Defines regular text<br />
id The identifier of the text enclosed with this tag<br />
style An inline style definition<br />
Defines strikethrough text<br />
id The identifier of the text enclosed with this tag<br />
70
style An inline style definition<br />
Defines a style used for rendering and formatting of the<br />
content<br />
align Specifies the content alignment<br />
backcolor Specifies the color of the object background<br />
backfadecolor Specifies the fading color of the object background<br />
bordercolor Specifies the color of the object border<br />
fillstyle Specifies the type of gradient fill of the object background<br />
font Specifies the color of the text<br />
hovercolor<br />
hoverfadecolor<br />
Specifies the color of the object background while mouse<br />
cursor hovers over it<br />
Specifies the fading color of the object background while mouse<br />
cursor hovers over it<br />
hovertextcolor Specifies the color of the text while mouse cursor hovers over it<br />
id The identifier of the style<br />
margin Defines the space around an object’s border<br />
padding<br />
Defines the space between the border and the content of an<br />
object<br />
rendering Specifies the rendering mode for text<br />
selectedtextcolor Specifies the color of the text when it is selected<br />
textcolor Specifies the color of the text<br />
transparency Specifies the percentage of transparency<br />
defines underlined text<br />
id The identifier of the text enclosed with this tag<br />
style An inline style definition<br />
In the following section we will present you how to use these tags in various combinations. As a<br />
result there would be created custom layouts for node’s content.<br />
Working with containers: and tags<br />
The simplest form of formatted content is constructed by using the tag and sample text.<br />
Here is an example:<br />
[VB]<br />
' Column<br />
column.HeaderContent = "First header line"<br />
column.FooterContent = "First footer line"<br />
' Node<br />
node.Content = "Single text line"<br />
[C#]<br />
// Column<br />
column.HeaderContent = "First header line";<br />
column.FooterContent = "First footer line";<br />
71
Node<br />
node.Content = "Single text line";<br />
In some cases you want to display text in multiple lines or in different paragraphs. For this<br />
situation the tag is used. Here is an example:<br />
[VB]<br />
' Column<br />
column.HeaderContent = "An example of a little longer header<br />
description"<br />
column.FooterContent = "An example of a little longer footer<br />
description"<br />
' Node<br />
node.Content = "An example of text in two paragraphs:The first paragraph has an indent set to 20 pixels. In this way the<br />
contained text is moved from the left border.The second paragraph shows<br />
short text line."<br />
[C#]<br />
// Column<br />
column.HeaderContent = "An example of a little longer header<br />
description";<br />
column.FooterContent = "An example of a little longer footer<br />
description";<br />
// Node<br />
node.Content = "An example of text in two paragraphs:The first paragraph has an indent set to 20 pixels. In this way the<br />
contained text is moved from the left border.The second paragraph shows<br />
short text line.";<br />
The result is shown in following pictures:<br />
From the pictures you can also notice that the text is wrapped in multiple lines when words are<br />
reaching the end of the node content space. This happens because the WordWrap property by<br />
default is set to True for all nodes in the <strong>TreeListView</strong> control.<br />
72
The same XML tags also can be used for subitems. Here is how it would look if the following code<br />
is applied:<br />
[VB]<br />
' At first set the type of column content to accept XML tags<br />
this.treeListView1.Columns[0].ContentType = ColumnContentType.Custom<br />
this.treeListView1.Columns[1].ContentType = ColumnContentType.Custom<br />
' SubItems<br />
<strong>TreeListView</strong>SubItem subItem = new <strong>TreeListView</strong>SubItem();<br />
subItem.Content = "First subitem"<br />
node.SubItems.Add(subItem)<br />
subItem = new <strong>TreeListView</strong>SubItem()<br />
subItem.Content = "Second subitem"<br />
node.SubItems.Add(subItem)<br />
this.treeListView1.UpdateLayout()<br />
[C#]<br />
// At first set the type of column content to accept XML tags<br />
this.treeListView1.Columns[0].ContentType = ColumnContentType.Custom;<br />
this.treeListView1.Columns[1].ContentType = ColumnContentType.Custom;<br />
// SubItems<br />
<strong>TreeListView</strong>SubItem subItem = new <strong>TreeListView</strong>SubItem();<br />
subItem.Content = "First subitem";<br />
node.SubItems.Add(subItem);<br />
subItem = new <strong>TreeListView</strong>SubItem();<br />
subItem.Content = "Second subitem";<br />
node.SubItems.Add(subItem);<br />
this.treeListView1.UpdateLayout();<br />
The code for the result in second picture is:<br />
[VB]<br />
' At first set the type of column content to accept XML tags<br />
Me.treeListView1.Columns(0).ContentType = ColumnContentType.[Custom]<br />
Me.treeListView1.Columns(1).ContentType = ColumnContentType.[Custom]<br />
' SubItems<br />
Dim subItem As New <strong>TreeListView</strong>SubItem()<br />
subItem.Content = "First subitem:The paragraph has<br />
an indent of 20 pixels.A short text line."<br />
node.SubItems.Add(subItem)<br />
subItem = New <strong>TreeListView</strong>SubItem()<br />
subItem.Content = "Second subitem:The paragraph has<br />
an indent of 20 pixels.A short text line."<br />
node.SubItems.Add(subItem)<br />
Me.treeListView1.UpdateLayout()<br />
[C#]<br />
// At first set the type of column content to accept XML tags<br />
73
this.treeListView1.Columns[0].ContentType = ColumnContentType.Custom;<br />
this.treeListView1.Columns[1].ContentType = ColumnContentType.Custom;<br />
// SubItems<br />
<strong>TreeListView</strong>SubItem subItem = new <strong>TreeListView</strong>SubItem();<br />
subItem.Content = "First subitem:The paragraph has<br />
an indent of 20 pixels.A short text line.";<br />
node.SubItems.Add(subItem);<br />
subItem = new <strong>TreeListView</strong>SubItem();<br />
subItem.Content = "Second subitem:The paragraph has<br />
an indent of 20 pixels.A short text line.";<br />
node.SubItems.Add(subItem);<br />
this.treeListView1.UpdateLayout();<br />
By default the WordWrap property for subitems is set to False. Because of this you can see that<br />
text is not wrapped in multiple lines when words are reaching the end of the subitem space. If we<br />
change this property value to true, the result is different<br />
[VB]<br />
' At first set the type of column content to accept XML tags<br />
Me.treeListView1.Columns(0).ContentType = ColumnContentType.[Custom]<br />
Me.treeListView1.Columns(1).ContentType = ColumnContentType.[Custom]<br />
' SubItems<br />
Dim subItem As New <strong>TreeListView</strong>SubItem()<br />
subItem.Content = "First subitem:The paragraph has<br />
an indent of 20 pixels.A short text line."<br />
subItem.WordWrap = True<br />
node.SubItems.Add(subItem)<br />
subItem = New <strong>TreeListView</strong>SubItem()<br />
subItem.Content = "Second subitem:The paragraph has<br />
an indent of 20 pixels.A short text line."<br />
subItem.WordWrap = True<br />
node.SubItems.Add(subItem)<br />
Me.treeListView1.UpdateLayout()<br />
74
[C#]<br />
// At first set the type of column content to accept XML tags<br />
this.treeListView1.Columns[0].ContentType = ColumnContentType.Custom;<br />
this.treeListView1.Columns[1].ContentType = ColumnContentType.Custom;<br />
// SubItems<br />
<strong>TreeListView</strong>SubItem subItem = new <strong>TreeListView</strong>SubItem();<br />
subItem.Content = "First subitem:The paragraph has<br />
an indent of 20 pixels.A short text line.";<br />
subItem.WordWrap = true;<br />
node.SubItems.Add(subItem);<br />
subItem = new <strong>TreeListView</strong>SubItem();<br />
subItem.Content = "Second subitem:The paragraph has<br />
an indent of 20 pixels.A short text line.";<br />
subItem.WordWrap = true;<br />
node.SubItems.Add(subItem);<br />
this.treeListView1.UpdateLayout();<br />
More information about word wrapping can be found in “Using word wrap” section of this<br />
document.<br />
Working with tag<br />
Normally some parts of the text shown in a single content can have different font or text size. In<br />
order to do that the tag is used.<br />
In following example we will present you how to create content with header, text in multiple lines<br />
with some parts set to different font and color.<br />
[VB]<br />
' At first set the type of column content to accept XML tags<br />
Me.treeListView1.Columns(0).ContentType = ColumnContentType.[Custom]<br />
' SubItems<br />
Dim subItem As New <strong>TreeListView</strong>SubItem()<br />
subItem.Content = "Header:Comic Sans MS<br />
75
font with text in green color"<br />
subItem.WordWrap = True<br />
Me.treeListView1.SelectedNode.SubItems.Add(subItem)<br />
Me.treeListView1.UpdateLayout()<br />
[C#]<br />
// At first set the type of column content to accept XML tags<br />
this.treeListView1.Columns[0].ContentType = ColumnContentType.Custom;<br />
// SubItems<br />
<strong>TreeListView</strong>SubItem subItem = new <strong>TreeListView</strong>SubItem();<br />
subItem.Content = "Header:Comic Sans MS<br />
font with text in green color";<br />
subItem.WordWrap = true;<br />
this.treeListView1.SelectedNode.SubItems.Add(subItem);<br />
this.treeListView1.UpdateLayout();<br />
The result is a text in two lines. First line is shown in Microsoft Sans Serif 11pt in blue color,<br />
and the second line is shown in Comic Sans MS font containing parts in green color:<br />
Working with font style tags<br />
In font style tags group are , , and . With these tags you can change the style of<br />
font for some part or whole text. Here is an example:<br />
[VB]<br />
node.Content = "Simple text line containing Bold, Italic,<br />
strikethrough and underline text."<br />
Me.treeListView1.UpdateLayout()<br />
[C#]<br />
node.Content = "Simple text line containing Bold, Italic,<br />
strikethrough and underline text.";<br />
this.treeListView1.UpdateLayout();<br />
76
Working with tag<br />
One of objects that you can create in content is a hyperlink object. The link you are entering can<br />
be some file or page located on the web or on local hard disk.<br />
If the link points to some application file like Notepad.exe, you can open it by simple clicking on<br />
the hyperlink. However in order this to work, you will also need to handle ItemObjectClicked<br />
event.<br />
Here is an example of content with two hyperlinks:<br />
[VB]<br />
' At first set the type of column content to accept XML tags<br />
Me.treeListView1.Columns(0).ContentType = ColumnContentType.[Custom]<br />
Me.treeListView1.Columns(1).ContentType = ColumnContentType.[Custom]<br />
' SubItems<br />
Dim subItem As New <strong>TreeListView</strong>SubItem()<br />
subItem.Content = "Search portal"<br />
subItem.WordWrap = True<br />
Me.treeListView1.SelectedNode.SubItems.Add(subItem)<br />
subItem = New <strong>TreeListView</strong>SubItem()<br />
subItem.Content = "Our company home page <strong>Lidor</strong> <strong>Systems</strong>"<br />
subItem.WordWrap = True<br />
Me.treeListView1.SelectedNode.SubItems.Add(subItem)<br />
Me.treeListView1.UpdateLayout()<br />
[C#]<br />
// At first set the type of column content to accept XML tags<br />
this.treeListView1.Columns[0].ContentType = ColumnContentType.Custom;<br />
this.treeListView1.Columns[1].ContentType = ColumnContentType.Custom;<br />
// SubItems<br />
<strong>TreeListView</strong>SubItem subItem = new <strong>TreeListView</strong>SubItem();<br />
subItem.Content = "Search portal";<br />
77
subItem.WordWrap = true;<br />
this.treeListView1.SelectedNode.SubItems.Add(subItem);<br />
subItem = new <strong>TreeListView</strong>SubItem();<br />
subItem.Content = "Our company home page <strong>Lidor</strong> <strong>Systems</strong>";<br />
subItem.WordWrap = true;<br />
this.treeListView1.SelectedNode.SubItems.Add(subItem);<br />
this.treeListView1.UpdateLayout();<br />
As you can see from the picture, the hyperlinks have also different colors. Also, the hand cursor is<br />
automatically shown when the mouse hovers over the hyperlink. In future versions we may<br />
extend this to be able to add custom cursors.<br />
In this example we have used the style attribute in which you can set different sub attributes for<br />
the object to which this style is applied. See below for more information how to use styles.<br />
Working with tag<br />
With this tag you can add images located on some local location or there is an option to create<br />
ImageList and extract the image from the list by using specified index.<br />
An example how to create content with two images located on local hard disk:<br />
[VB]<br />
' Column<br />
' An example how to create content with two images located on local hard disk<br />
Me.treeListView1.Columns(0).HeaderContent = " Content created with two images at different locations."<br />
' An example how to create content with two images located in ImageList<br />
referenced by <strong>TreeListView</strong> control<br />
Me.treeListView1.Columns(0).FooterContent = " Content<br />
created with two images . Images are contained in<br />
ImageList."<br />
Me.treeListView1.Columns(0).WordWrap = True<br />
78
Me.treeListView1.UpdateLayout()<br />
[C#]<br />
// Column<br />
// An example how to create content with two images located on local hard disk<br />
this.treeListView1.Columns[0].HeaderContent = " Content created with two images at different locations.";<br />
// An example how to create content with two images located in ImageList<br />
referenced by <strong>TreeListView</strong> control<br />
this.treeListView1.Columns[0].FooterContent = "<br />
Content created with two images . Images are contained in<br />
ImageList.";<br />
this.treeListView1.Columns[0].WordWrap = true;<br />
this.treeListView1.UpdateLayout();<br />
By default the images have their original size. You can change their size by setting the width and<br />
height attributes of the tag. Also you can apply margin and padding attributes by setting<br />
the style attribute values (see below how to use styles).<br />
Working with tag<br />
With text, images and hyperlinks you can create very rich content. However, placing custom<br />
controls will give more interaction to the user.<br />
The tag is specifically added to meet this task. Every custom control, standard or third<br />
party, can be placed in single content of the column, node or subitem. You can add even complex<br />
controls like Grid.<br />
Here is an example on how to add a button and a checkbox to subitem content:<br />
[VB]<br />
' At first set the type of column content to accept XML tags<br />
Me.treeListView1.Columns(0).ContentType = ColumnContentType.[Custom]<br />
' SubItem<br />
Dim subItem As New <strong>TreeListView</strong>SubItem()<br />
79
' At first the control must be created and added to<br />
' the subitem Controls collection<br />
Dim cBox As New CheckBox()<br />
cBox.Size = New Size(14, 14)<br />
subItem.Controls.Add(cBox)<br />
' In tag use the index to reference the control<br />
subItem.Content = "Content with custom control. "<br />
Me.treeListView1.SelectedNode.SubItems.Add(subItem)<br />
Me.treeListView1.UpdateLayout()<br />
[C#]<br />
// At first set the type of column content to accept XML tags<br />
this.treeListView1.Columns[0].ContentType = ColumnContentType.Custom;<br />
// SubItem<br />
<strong>TreeListView</strong>SubItem subItem = new <strong>TreeListView</strong>SubItem();<br />
// At first the control must be created and added to<br />
// the subitem Controls collection<br />
CheckBox cBox = new CheckBox();<br />
cBox.Size = new Size(14, 14);<br />
subItem.Controls.Add(cBox);<br />
// In tag use the index to reference the control<br />
subItem.Content = "Content with custom control. ";<br />
this.treeListView1.SelectedNode.SubItems.Add(subItem);<br />
this.treeListView1.UpdateLayout();<br />
The use of controls in simple format is not very useful. The controls like text or any other object<br />
can also we wrapped and shown in next line, but that is all. Mainly in simple form there are no<br />
attributes by which you can place the control at specific place or aligned it to the right side of the<br />
content space, for example.<br />
This can be done by using table formatting which is explained in next section.<br />
80
Working with , and tags<br />
The best way to create custom layouts with different objects placed at different locations in the<br />
content is by using table formatting.<br />
One of the reasons the table is used is presentation of data in ordered way for all nodes. In the<br />
following example we will show you how to place a text, hyperlink and custom control in a content<br />
using tag:<br />
[VB]<br />
' At first set the type of column content to accept XML tags<br />
Me.treeListView1.Columns(1).ContentType = ColumnContentType.[Custom]<br />
' SubItem<br />
Dim subItem As New <strong>TreeListView</strong>SubItem("Subitem")<br />
Me.treeListView1.SelectedNode.SubItems.Add(subItem)<br />
subItem = New <strong>TreeListView</strong>SubItem()<br />
' At first the control must be created and added to<br />
' the subitem Controls collection<br />
Dim cBox As New CheckBox()<br />
cBox.Size = New Size(14, 14)<br />
subItem.Controls.Add(cBox)<br />
' In tag use the index to reference the control<br />
subItem.Content = "Simple<br />
text lineMore info"<br />
Me.treeListView1.SelectedNode.SubItems.Add(subItem)<br />
Me.treeListView1.UpdateLayout()<br />
[C#]<br />
// At first set the type of column content to accept XML tags<br />
this.treeListView1.Columns[1].ContentType = ColumnContentType.Custom;<br />
// SubItem<br />
<strong>TreeListView</strong>SubItem subItem = new <strong>TreeListView</strong>SubItem("Subitem");<br />
this.treeListView1.SelectedNode.SubItems.Add(subItem);<br />
subItem = new <strong>TreeListView</strong>SubItem();<br />
// At first the control must be created and added to<br />
// the subitem Controls collection<br />
CheckBox cBox = new CheckBox();<br />
cBox.Size = new Size(14, 14);<br />
subItem.Controls.Add(cBox);<br />
// In tag use the index to reference the control<br />
subItem.Content = "Simple<br />
text lineMore info";<br />
this.treeListView1.SelectedNode.SubItems.Add(subItem);<br />
this.treeListView1.UpdateLayout();<br />
81
In this example all three objects are placed next to each other, which doesn’t give the best look.<br />
Also, it acts like there is not table present. We can change that by specifying the width for each<br />
table cell. If the width is not specified the table cell will have width of the object with minimal<br />
width.<br />
[VB]<br />
' At first set the type of column content to accept XML tags<br />
Me.treeListView1.Columns(1).ContentType = ColumnContentType.[Custom]<br />
' SubItem<br />
Dim subItem As New <strong>TreeListView</strong>SubItem("Subitem")<br />
Me.treeListView1.SelectedNode.SubItems.Add(subItem)<br />
subItem = New <strong>TreeListView</strong>SubItem()<br />
' At first the control must be created and added to<br />
' the subitem Controls collection<br />
Dim cBox As New CheckBox()<br />
cBox.Size = New Size(14, 14)<br />
subItem.Controls.Add(cBox)<br />
' In tag use the index to reference the control<br />
subItem.Content = "Simple text lineMore info<br />
"<br />
subItem.WordWrap = True<br />
Me.treeListView1.SelectedNode.SubItems.Add(subItem)<br />
Me.treeListView1.UpdateLayout()<br />
[C#]<br />
// At first set the type of column content to accept XML tags<br />
this.treeListView1.Columns[1].ContentType = ColumnContentType.Custom;<br />
// SubItem<br />
<strong>TreeListView</strong>SubItem subItem = new <strong>TreeListView</strong>SubItem("Subitem");<br />
this.treeListView1.SelectedNode.SubItems.Add(subItem);<br />
subItem = new <strong>TreeListView</strong>SubItem();<br />
// At first the control must be created and added to<br />
// the subitem Controls collection<br />
82
CheckBox cBox = new CheckBox();<br />
cBox.Size = new Size(14, 14);<br />
subItem.Controls.Add(cBox);<br />
// In tag use the index to reference the control<br />
subItem.Content = "Simple text lineMore info<br />
";<br />
subItem.WordWrap = true;<br />
this.treeListView1.SelectedNode.SubItems.Add(subItem);<br />
this.treeListView1.UpdateLayout();<br />
The change is obvious. By specifying the width of table cell in percents we have achieved the cell<br />
to shrink or expand depending of the current width of the subitem content. For the last cell the<br />
width is not specified. This is done to make sure that the CheckBox will remain always docked at<br />
the right side of the content.<br />
Here is a more complex layout, which includes column and row span:<br />
[VB]<br />
' At first set the type of column content to accept XML tags<br />
Me.treeListView1.Columns(1).ContentType = ColumnContentType.[Custom]<br />
' SubItem<br />
Dim subItem As New <strong>TreeListView</strong>SubItem("Subitem")<br />
Me.treeListView1.SelectedNode.SubItems.Add(subItem)<br />
subItem = New <strong>TreeListView</strong>SubItem()<br />
' At first the control must be created and added to<br />
' the subitem Controls collection<br />
Dim cBox As New CheckBox()<br />
cBox.Size = New Size(14, 14)<br />
subItem.Controls.Add(cBox)<br />
' Use a temprary variable for storing large string<br />
Dim content As String = ""<br />
' Add the first row with four cells<br />
content += "First line
style=""textcolor:Blue"">More info"<br />
' Add the second row and span the cell over three other cells<br />
content += "Second text line which is a little longer."<br />
' Close the table and div tags<br />
content += ""<br />
' Add the content string to the subItem Content property<br />
subItem.Content = content<br />
subItem.WordWrap = True<br />
Me.treeListView1.SelectedNode.SubItems.Add(subItem)<br />
Me.treeListView1.UpdateLayout()<br />
[C#]<br />
// At first set the type of column content to accept XML tags<br />
this.treeListView1.Columns[1].ContentType = ColumnContentType.Custom;<br />
// SubItem<br />
<strong>TreeListView</strong>SubItem subItem = new <strong>TreeListView</strong>SubItem("Subitem");<br />
this.treeListView1.SelectedNode.SubItems.Add(subItem);<br />
subItem = new <strong>TreeListView</strong>SubItem();<br />
// At first the control must be created and added to<br />
// the subitem Controls collection<br />
CheckBox cBox = new CheckBox();<br />
cBox.Size = new Size(14, 14);<br />
subItem.Controls.Add(cBox);<br />
// Use a temprary variable for storing large string<br />
String content = "";<br />
// Add the first row with four cells<br />
content += "First lineMore info";<br />
// Add the second row and span the cell over three other cells<br />
content += "Second text line which is a little longer.";<br />
// Close the table and div tags<br />
content += "";<br />
// Add the content string to the subItem Content property<br />
subItem.Content = content;<br />
subItem.WordWrap = true;<br />
this.treeListView1.SelectedNode.SubItems.Add(subItem);<br />
this.treeListView1.UpdateLayout();<br />
The first cell is spanned across two rows. The second cell of the second row is spanned across<br />
three columns. The result is shown in following picture:<br />
84
Working with tag<br />
The styles are very powerful tool if you use them correctly. You can create several styles in<br />
beginning and later used them for specific parts of the code only by calling their Id. Also you can<br />
use inline coding to apply specific style to some part of the content.<br />
Here is how to create styles at beginning of the code:<br />
[VB]<br />
' Use a temprary variable for storing large string<br />
Dim content As String = ""<br />
content += ""<br />
content += ""<br />
content += "The first text line in red."<br />
content += "The second in blue, with parts<br />
in green."<br />
content += ""<br />
' Add the content string to the subItem Content property<br />
subItem.Content = content<br />
subItem.WordWrap = True<br />
[C#]<br />
// Use a temprary variable for storing large string<br />
String content = "";<br />
content += "";<br />
content += "";<br />
content += "The first text line in red.";<br />
content += "The second in blue, with parts<br />
in green.";<br />
content += "";<br />
// Add the content string to the subItem Content property<br />
subItem.Content = content;<br />
85
subItem.WordWrap = true;<br />
Here is how to use inline style definition:<br />
[VB]<br />
' Use a temprary variable for storing large string<br />
Dim content As String = ""<br />
content += "The first text line in<br />
red."<br />
content += "The second in blue,<br />
with parts in<br />
green."<br />
content += ""<br />
' Add the content string to the subItem Content property<br />
subItem.Content = content<br />
subItem.WordWrap = True<br />
[C#]<br />
// Use a temprary variable for storing large string<br />
String content = "";<br />
content += "The first text line in<br />
red.";<br />
content += "The second in blue,<br />
with parts in<br />
green.";<br />
content += "";<br />
// Add the content string to the subItem Content property<br />
subItem.Content = content;<br />
subItem.WordWrap = true;<br />
The result is the same as in previous picture, only the use of styles has changed. Instead of using<br />
predefined styles, we have used inline style definitions to change different parts of the text.<br />
Styles can be applied for every object, not just text. For example the Margin and Padding<br />
attributes of the style, has more value when paragraphs or tables are used. The same applies for<br />
content alignment which has more value when it is used with tables.<br />
86
Using word wrap<br />
By default the WordWrap for the <strong>TreeListView</strong> control and all nodes is set to True. This means that<br />
whenever some object reach the end of the line, if there is not enough space for the object to be<br />
placed at the line end, it will be placed in beginning of a new line. In this way by changing the<br />
width of columns in <strong>TreeListView</strong> control the content of their nodes will expand or collapse , but<br />
always will show their full content in visible area of the control. However, for columns and<br />
subitems the WordWrap property by default is set to False. In order to work this for them, at first<br />
this value must be set to True.<br />
If you don’t want to use word wrapping, then the node content will remain in exact place as node<br />
layout is constructed. Meaning, some objects may be placed outside the visible area of the<br />
<strong>TreeListView</strong> control. This will trigger appearance of horizontal or vertical scrollbar, which allows<br />
you to scroll the visible area in order to show these objects.<br />
As stated above, all nodes can have their independent setting of word wrap. This is very useful to<br />
have, when designing different layouts for different nodes. Some of them can have word wrapping<br />
while others don’t. You only need to change the WordWrap property for specific nodes.<br />
87
Serialization<br />
You can use serialization to memorize the current state of <strong>TreeListView</strong>. Also, this feature is very<br />
useful in creation of color schemes.<br />
How to serialize the control content in Streams<br />
In order to serialize the control content in streams, there are two methods:<br />
• LoadFromStream – load the control content from Stream<br />
• SaveToStream – save the control content in Stream<br />
Here is how you can use these methods:<br />
[VB]<br />
Imports <strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Serialization<br />
. . .<br />
' Create a MemoryStream object<br />
Private memStream As New MemoryStream()<br />
' Click on the btnLoad button to load the content of MemoryStream object<br />
' to <strong>TreeListView</strong> control<br />
Private Sub btnLoad_Click(ByVal sender As Object, ByVal e As System.EventArgs)<br />
Dim serializer As New <strong>TreeListView</strong>Serializer()<br />
memStream.Seek(0, SeekOrigin.Begin)<br />
serializer.LoadFromStream(Me.treeListView1, memStream)<br />
End Sub<br />
' Click on the btnSave button to save the control content to<br />
' MemoryStream object<br />
Private Sub btnSave_Click(ByVal sender As Object, ByVal e As System.EventArgs)<br />
Dim serializer As New <strong>TreeListView</strong>Serializer()<br />
serializer.SaveToStream(Me.treeListView1, memStream, False)<br />
End Sub<br />
[C#]<br />
using <strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Serialization;<br />
. . .<br />
// Create a MemoryStream object<br />
MemoryStream memStream = new MemoryStream();<br />
// Click on the btnLoad button to load the content of MemoryStream object<br />
// to <strong>TreeListView</strong> control<br />
private void btnLoad_Click(object sender, System.EventArgs e)<br />
{<br />
<strong>TreeListView</strong>Serializer serializer = new <strong>TreeListView</strong>Serializer();<br />
memStream.Seek(0, SeekOrigin.Begin);<br />
serializer.LoadFromStream(this.treeListView1, memStream);<br />
}<br />
// Click on the btnSave button to save the control content to<br />
// MemoryStream object<br />
private void btnSave_Click(object sender, System.EventArgs e)<br />
88
{<br />
}<br />
<strong>TreeListView</strong>Serializer serializer = new <strong>TreeListView</strong>Serializer();<br />
serializer.SaveToStream(this.treeListView1, memStream, false);<br />
How to serialize the control content in files<br />
In order to serialize the control content in files, there are two ways:<br />
• By using file streams<br />
• By using file names<br />
Serialization using file streams<br />
[VB]<br />
Imports <strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Serialization<br />
. . .<br />
' Click on the btnLoad button to load the content of FileStream object<br />
' to <strong>TreeListView</strong> control<br />
Private Sub btnLoad_Click(ByVal sender As Object, ByVal e As System.EventArgs)<br />
Dim serializer As New <strong>TreeListView</strong>Serializer()<br />
Dim fs As FileStream = File.OpenRead("C:\fs.xml")<br />
serializer.LoadFromStream(Me.treeListView1, fs)<br />
End Sub<br />
' Click on the btnSave button to save the control content to<br />
' FileStream object<br />
Private Sub btnSave_Click(ByVal sender As Object, ByVal e As System.EventArgs)<br />
Dim serializer As New <strong>TreeListView</strong>Serializer()<br />
Dim fs As FileStream = File.Create("C:\fs.xml")<br />
serializer.SaveToStream(Me.treeListView1, fs, True)<br />
End Sub<br />
[C#]<br />
using <strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Serialization;<br />
. . .<br />
// Click on the btnLoad button to load the content of FileStream object<br />
// to <strong>TreeListView</strong> control<br />
private void btnLoad_Click(object sender, System.EventArgs e)<br />
{<br />
<strong>TreeListView</strong>Serializer serializer = new <strong>TreeListView</strong>Serializer();<br />
FileStream fs = File.OpenRead("C:\\fs.xml");<br />
serializer.LoadFromStream(this.treeListView1, fs);<br />
}<br />
// Click on the btnSave button to save the control content to<br />
// FileStream object<br />
private void btnSave_Click(object sender, System.EventArgs e)<br />
{<br />
<strong>TreeListView</strong>Serializer serializer = new <strong>TreeListView</strong>Serializer();<br />
FileStream fs = File.Create("C:\\fs.xml");<br />
serializer.SaveToStream(this.treeListView1, fs, true);<br />
}<br />
89
Serialization using file names<br />
In order to serialize the control content in files, there are two methods:<br />
• LoadFromFile – load the control content from file<br />
• SaveToFile – save the control content in file<br />
[VB]<br />
' Click on the btnLoad button to open the Load dialog, by which you can<br />
' choose the destination of the file<br />
Private Sub btnLoad_Click(ByVal sender As Object, ByVal e As System.EventArgs)<br />
Dim openDlg As New OpenFileDialog()<br />
openDlg.Filter = "XML files (*.xml)|*.xml"<br />
openDlg.InitialDirectory = Application.ExecutablePath<br />
If openDlg.ShowDialog() = DialogResult.OK Then<br />
Me.treeListView1.SuspendUpdate()<br />
Dim serializer As New<br />
<strong>Lidor</strong><strong>Systems</strong>.IntregralUI.Serialization.<strong>TreeListView</strong>Serializer()<br />
serializer.LoadFromXml(Me.treeListView1, openDlg.FileName)<br />
Me.treeListView1.ResumeUpdate()<br />
End If<br />
End Sub<br />
' Click on the btnSave button to open the Save dialog, by which you can<br />
' choose the destination of the file<br />
Private Sub btnSave_Click(ByVal sender As Object, ByVal e As System.EventArgs)<br />
Dim saveDlg As New SaveFileDialog()<br />
saveDlg.Filter = "XML files (*.xml)|*.xml"<br />
saveDlg.AddExtension = True<br />
saveDlg.DefaultExt = ".xml"<br />
saveDlg.InitialDirectory = Application.ExecutablePath<br />
If saveDlg.ShowDialog() = DialogResult.OK Then<br />
Dim serializer As New<br />
<strong>Lidor</strong><strong>Systems</strong>.IntregralUI.Serialization.<strong>TreeListView</strong>Serializer()<br />
serializer.SaveToXml(Me.treeListView1, saveDlg.FileName)<br />
End If<br />
End Sub<br />
[C#]<br />
using <strong>Lidor</strong><strong>Systems</strong>.<strong>IntegralUI</strong>.Serialization;<br />
. . .<br />
// Click on the btnLoad button to open the Load dialog, by which you can<br />
// choose the destination of the file<br />
private void btnLoad_Click(object sender, System.EventArgs e)<br />
{<br />
OpenFileDialog openDlg = new OpenFileDialog();<br />
openDlg.Filter = "XML files (*.xml)|*.xml";<br />
openDlg.InitialDirectory = Application.ExecutablePath;<br />
if (openDlg.ShowDialog() == DialogResult.OK)<br />
{<br />
this.treeListView1.SuspendUpdate();<br />
<strong>Lidor</strong><strong>Systems</strong>.IntregralUI.Serialization.<strong>TreeListView</strong>Serializer serializer =<br />
new <strong>Lidor</strong><strong>Systems</strong>.IntregralUI.Serialization.<strong>TreeListView</strong>Serializer();<br />
90
}<br />
}<br />
serializer.LoadFromXml(this.treeListView1, openDlg.FileName);<br />
this.treeListView1.ResumeUpdate();<br />
// Click on the btnSave button to open the Save dialog, by which you can<br />
// choose the destination of the file<br />
private void btnSave_Click(object sender, System.EventArgs e)<br />
{<br />
SaveFileDialog saveDlg = new SaveFileDialog();<br />
saveDlg.Filter = "XML files (*.xml)|*.xml";<br />
saveDlg.AddExtension = true;<br />
saveDlg.DefaultExt = ".xml";<br />
saveDlg.InitialDirectory = Application.ExecutablePath;<br />
if (saveDlg.ShowDialog() == DialogResult.OK)<br />
{<br />
<strong>Lidor</strong><strong>Systems</strong>.IntregralUI.Serialization.<strong>TreeListView</strong>Serializer serializer =<br />
<strong>Lidor</strong><strong>Systems</strong>.IntregralUI.Serialization.new <strong>TreeListView</strong>Serializer();<br />
serializer.SaveToXml(this.treeListView1, saveDlg.FileName);<br />
}<br />
}<br />
How to serialize the control content in SQL database<br />
When you want to save the control content in some SQL database, at first you need a XML field in<br />
your table. The process of adding the control content to this field is the same as for streams,<br />
explained previously.<br />
Loading content from a database and filling the <strong>TreeListView</strong> control with it is also the same as<br />
using streams. But here, at first you need to create a MemoryObject:<br />
[VB]<br />
' Create a MemoryStream object<br />
Dim memStream As New MemoryStream()<br />
' sampleString is temporary varaiable that holds the database XMl field content<br />
' In this demonstration we are using some XML encoded text.<br />
Dim sampleString As String = ""<br />
' Write the sampleString to the MemoryStream object<br />
Dim sw As New StreamWriter(memStream, System.Text.Encoding.ASCII)<br />
sw.Write(sampleString)<br />
sw.Flush()<br />
[C#]<br />
// Create a MemoryStream object<br />
MemoryStream memStream = new MemoryStream();<br />
// sampleString is temporary varaiable that holds the database XMl field content<br />
// In this demonstration we are using some XML encoded text.<br />
string sampleString = "";<br />
91
Write the sampleString to the MemoryStream object<br />
StreamWriter sw = new StreamWriter(memStream, System.Text.Encoding.ASCII);<br />
sw.Write(sampleString);<br />
sw.Flush();<br />
After that, you need to create a <strong>TreeListView</strong>Serializer object:<br />
[VB]<br />
Dim serializer As New <strong>TreeListView</strong>Serializer()<br />
memStream.Seek(0, SeekOrigin.Begin)<br />
serializer.LoadFromStream(Me.treeListView1, memStream)<br />
[C#]<br />
<strong>TreeListView</strong>Serializer serializer = new <strong>TreeListView</strong>Serializer();<br />
memStream.Seek(0, SeekOrigin.Begin);<br />
serializer.LoadFromStream(this.treeListView1, memStream);<br />
As a result the control will be populated from the string placed in the MemoryStream object.<br />
92
Sample projects<br />
More information on <strong>IntegralUI</strong> <strong>TreeListView</strong> control can be found by examining the source code of<br />
sample projects available on our web site:<br />
Explorer<br />
Demonstrates how <strong>IntegralUI</strong> <strong>TreeListView</strong>control can be used to<br />
create a Windows Explorer - like application. It includes various<br />
appearances, three visual styles (Classic, XP, Vista), Advanced<br />
Drag&Drop operations, Column reordering, Sorting and Multiple<br />
selections. Among the advanced features is the XML encoding of<br />
column and node text.<br />
Custom Controls<br />
Demonstrates how custom controls can be included in <strong>IntegralUI</strong><br />
<strong>TreeListView</strong>. Data is presented in advanced detail view with fixed<br />
columns to the left and right side, with several types of custom<br />
controls. Three visual styles (Classic, XP, Vista) are available.<br />
93