19.04.2013 Views

IntegralUI TreeListView User Guide - Lidor Systems

IntegralUI TreeListView User Guide - Lidor Systems

IntegralUI TreeListView User Guide - Lidor Systems

SHOW MORE
SHOW LESS

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

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!