Tải bản đầy đủ (.pdf) (105 trang)

Mastering Microsoft Visual Basic 2010 phần 4 ppsx

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (983.16 KB, 105 trang )

THE RICHTEXTBOX CONTROL 283
Listing 7.13: Undoing and redoing actions
Private Sub RedoToolStripMenuItem_Click(…) Handles
RedoToolStripMenuItem.Click
If Editor.CanRedo Then Editor().Redo()
End Sub
Private Sub UndoToolStripMenuItem_Click(…) Handles
UndoToolStripMenuItem.Click
If Editor.CanUndo Then Editor.Undo()
End Sub
Calling the CanUndo and CanRedo method is unnecessary; if the corresponding action can’t
be performed, the two menu items will be disabled, but an additional check does no harm.
The Format Menu
The commands of the Format menu control the alignment and the font attributes of the current
selection. The Font command displays the Font dialog box and then assigns the font selected by
the user to the current selection. Listing 7.14 shows the code behind the Font command.
Listing 7.14: The Font command
Private Sub FontToolStripMenuItem_Click(…) Handles
FontToolStripMenuItem.Click
If Not Editor.SelectionFont Is Nothing Then
FontDialog1.Font = Editor.SelectionFont
Else
FontDialog1.Font = Nothing
End If
FontDialog1.ShowApply = True
If FontDialog1.ShowDialog() = DialogResult.OK Then
Editor.SelectionFont = FontDialog1.Font
End If
End Sub
Notice that the code preselects a font in the dialog box, the font of the current selection. If
the current selection isn’t formatted with a single font, no font is preselected.


To enable the Apply button of the Font dialog box, set the control’s ShowApply property to
True and insert the following statement in its Apply event handler:
Private Sub FontDialog1_Apply( ) Handles FontDialog1.Apply
Editor.SelectionFont = FontDialog1.Font
Editor.SelectionColor = FontDialog1.Color
End Sub
284 CHAPTER 7 MORE WINDOWS CONTROLS
The options of the Align menu set the RichTextBox control’s SelectionAlignment property
to different members of the HorizontalAlignment enumeration. The Align  Left command,
for example, is implemented with the following statement:
Editor.SelectionAlignment = HorizontalAlignment.Left
The Search & Replace Dialog Box
The Find command in the Edit menu opens the dialog box shown in Figure 7.9, which
performs search-and-replace operations (whole-word or case-sensitive match or both). The
Search & Replace form (it’s the frmFind form in the project) has its TopMost property set
to True so that it remains visible while it’s open, even if it doesn’t have the focus. The code
behind the buttons on this form is quite similar to the code for the Find & Replace dialog
box of the TextPad application, with one basic difference: the RTFPad project’s code uses the
RichTextBox control’s Find method; the simple TextBox control doesn’t provide an equivalent
method and we had to use the methods of the String class to perform the same operations. The
Find method of the RichTextBox control performs all types of searches, and some of its options
are not available with the IndexOf method of the String class.
Figure 7.9
The Search & Replace
dialog box of the RTFPad
application
To invoke the Search & Replace dialog box, the code calls the Show method of the frmFind
form, as discussed in Chapter 5, via the following statement:
frmFind.Show()
The Find method of the RichTextBox control allows you to perform case-sensitive or

-insensitive searches as well as search for whole words only. These options are specified
throughanargumentoftheRichTextBoxFinds type. The SetSearchMode() function (see
Listing 7.15) examines the settings of the two check boxes at the bottom of the form and sets
the mode variable, which represents the Find method’s search mode.
THE RICHTEXTBOX CONTROL 285
Listing 7.15: Setting the search options
Function SetSearchMode() As RichTextBoxFinds
Dim mode As RichTextBoxFinds =
RichTextBoxFinds.None
If chkCase.Checked = True Then
mode = mode Or RichTextBoxFinds.MatchCase
End If
If chkWord.Checked = True Then
mode = mode Or RichTextBoxFinds.WholeWord
End If
Return mode
End Function
The Click event handlers of the Find and Find Next buttons call this function to retrieve
the constant that determines the type of search specified by the user on the form. This value is
then passed to the Find method. Listing 7.16 shows the code behind the Find and Find Next
buttons.
Listing 7.16: The Find and Find Next commands
Private Sub bttnFind_Click(…) Handles bttnFind.Click
Dim wordAt As Integer
Dim srchMode As RichTextBoxFinds
srchMode = SetSearchMode()
wordAt = frmEditor.Editor.Find(
txtSearchWord.Text, 0, srchMode)
If wordAt = -1 Then
MsgBox("Can’t find word")

Exit Sub
End If
frmEditor.Editor.Select(wordAt, txtSearchWord.Text.Length)
bttnFindNext.Enabled = True
bttnReplace.Enabled = True
bttnReplaceAll.Enabled = True
frmEditor.Editor.ScrollToCaret()
End Sub
Private Sub bttnFindNext_Click(…) Handles bttnFindNext.Click
Dim selStart As Integer
Dim srchMode As RichTextBoxFinds
srchMode = SetSearchMode()
selStart = frmEditor.Editor.Find(
txtSearchWord.Text,
frmEditor.Editor.SelectionStart + 2,
srchMode)
286 CHAPTER 7 MORE WINDOWS CONTROLS
If selStart = -1 Then
MsgBox("No more matches")
Exit Sub
End If
frmEditor.Editor.Select(
selStart, txtSearchWord.Text.Length)
frmEditor.Editor.ScrollToCaret()
End Sub
Notice that both event handlers call the ScrollToCaret method to force the selected text to
become visible — should the Find method locate the desired string outside the visible segment
of the text.
The TreeView and ListView Controls
The TreeView and ListView controls are among the more advanced Windows controls and

they certainly are more difficult to program than the others discussed. However, these two
controls are the basic makings of unique user interfaces, as you will see in the examples
in the following sections. The ListView and TreeView controls are discussed in detail in
the tutorial ‘‘The ListView and TreeView controls,’’ which is available for download from
www.sybex.com/go/masteringvb2010. In this chapter, you will find an introduction to these
two controls and their basic properties and methods. For more information on using these
controls in your interface and interesting examples, please read the tutorial.
Figure 7.10 shows the TreeView and ListView controls used in tandem. What you see in
Figure 7.10 is Windows Explorer, a utility for examining and navigating your hard disk’s struc-
ture. The left pane, where the folders are displayed, is a TreeView control. The folder names are
displayed in a manner that reflects their structure on the hard disk. You can expand and con-
tract certain branches and view only the segment(s) of the tree structure you’re interested in.
Figure 7.10
Windows Explorer i s
made up of a Tree-
View (left pane) and
a ListView (right pane)
control.
THE TREEVIEW AND LISTVIEW CONTROLS 287
The right pane is a ListView control. The items on the ListView control can be displayed in
five ways (as large or small icons, as a list, on a grid, or tiled). They are the various views you
can set through the View menu of Windows Explorer. Although most people prefer to look at
the contents of the folders as icons, the most common view is the Details view, which displays
not only filenames, but also their attributes. In the Details view, the list can be sorted according
to any of its columns, making it easy for the user to locate any item based on various criteria
(file type, size, creation date, and so on).
Tree and List Structures
The TreeView control implements a data structure known as a tree. A tree is the most appro-
priate structure for storing hierarchical information. The organizational chart of a company, for
example, is a tree structure. Every person reports to another person above him or her, all the

way to the president or CEO. Figure 7.11 depicts a possible organization of continents, coun-
tries, and cities as a tree. Every city belongs to a country, and every country to a continent. In
the same way, every computer file belongs to a folder that may belong to an even bigger folder,
and so on up to the drive level. You can’t draw large tree structures on paper, but it’s possible
to create a similar structure in the computer’s memory without size limitations.
Figure 7.11
The world viewed
as a tree
Globe Root node
First-level nodes
Second-level nodes
Third-level nodes
Africa Asia Europe



Germany France Spain
Berlin Munich Frankfurt
S. America
Each item in the tree of Figure 7.11 is called a node, and nodes can be nested to any level.
Oddly, the top node is the root of the tree, and the subordinate nodes are called child nodes.If
you try to visualize this structure as a real tree, think of it as an upside-down tree with the
branches emerging from the root. The end nodes, which don’t lead to any other nodes, are
called leaf nodes or end nodes.
To locate a city, you must start at the root node and select the continent to which the city
belongs. Then you must find the country (in the selected continent) to which the city belongs.
Finally, you can find the city you’re looking for. If it’s not under the appropriate country node,
it doesn’t exist.
TreeView Items Are Just Strings
The items displayed on a TreeView control are just strings. Moreover, the TreeView control

doesn’t require that t he items be unique. You can have identically named nodes in the same
branch — as unlikely as this might be for a real application. There’s no property that m akes a
node unique in the tree structure or even in its own branch.
288 CHAPTER 7 MORE WINDOWS CONTROLS
You can also start with a city and find its country. The country node is the city node’s parent
node. Notice that there is only one route from child nodes to their parent nodes, which means
that you can instantly locate the country or continent of a city. The data shown in Figure 7.11 is
shown in Figure 7.12 in a TreeView control. Only the nodes we’re interested in are expanded.
The plus sign indicates that the corresponding node contains child nodes. To view them, end
users click the button with the plus sign and expand the node.
Figure 7.12
The nodes shown in
Figure 7.11 implemented
with a TreeView control
The tree structure is ideal for data with parent-child relations (relations that can be described
as belongs to or owns). The continents-countries-cities data is a typical example. The folder struc-
ture on a hard disk is another typical example. Any given folder is the child of another folder
or the root folder.
Maintaining a tree structure is a fundamental operation in software design; computer sci-
ence students spend a good deal of their time implementing tree structures. Fortunately, with
Visual Basic you don’t have to implement tree structures on your own. The TreeView control is
a mechanism for storing hierarchically structured data in a control with a visible interface. The
TreeView control hides (or encapsulates, in object-oriented terminology) the details of the imple-
mentation and allows you to set up tree structures with a few lines of code — in short, all the
gain without the pain (almost).
The ListView control implements a simpler structure, known as a list. A list’s items aren’t
structured in a hierarchy; they are all on the same level and can be traversed serially, one
after the other. You can also think of the list as a multidimensional array, but the list offers
more features. A list item can have subitems and can be sorted according to any column. For
example, you can set up a list of customer names (the list’s items) and assign a number of

subitems to each customer: a contact, an address, a phone number, and so on. Or you can set
up a list of files with their attributes as subitems. Figure 7.13 shows a Windows folder mapped
on a ListView control. Each file is an item, and its attributes are the subitems. As you already
know, you can sort this list by filename, size, file type, and so on. All you have to do is click
the header of the corresponding column.
The ListView control is a glorified ListBox control. If all you need is a control to store
sorted objects, use a ListBox control. If you want more features, such as storing multiple
items per row, sorting them in different ways, or locating them based on any subitem’s
THE TREEVIEW AND LISTVIEW CONTROLS 289
value, you must consider the ListView control. You can also look at the ListView control as a
view-only grid.
Figure 7.13
A folder’s files displayed
in a ListView control
(Details view)
The TreeView and ListView controls are commonly used along with the ImageList control.
The ImageList control is a simple control for storing images so they can be retrieved quickly
and used at runtime. You populate the ImageList control with the images you want to use on
your interface, usually at design time, and then you recall them by an index value at runtime.
The TreeView Control
Let’s start our discussion of the TreeView control with a few simple properties that you can
set at design time. To experiment with the properties discussed in this section, open the Tree-
ViewDemo project, available for download from www.sybex.com/go/masteringvb2010.The
project’s main form is shown in Figure 7.14. After setting some properties (they are discussed
next), run the project and click the Populate button to populate the control. After that, you can
click the other buttons to see the effect of the various property settings on the control.
Figure 7.14
The TreeViewDemo
project demonstrates
the basic properties and

methods of the Tree-
View control.
290 CHAPTER 7 MORE WINDOWS CONTROLS
Here are the basic properties that determine the appearance of the control:
CheckBoxes If this property is True, a check box appears in front of each node. If the con-
trol displays check boxes, you can select multiple nodes; otherwise, you’re limited to a single
selection.
FullRowSelect This True/False value determines whether a node will be selected even if the
user clicks outside the node’s caption.
HideSelection This property determines whether the selected node will remain highlighted
when the focus is moved to another control. By default, the selected node doesn’t remain high-
lighted when the control loses the focus.
HotTracking This property is another True/False value that determines whether nodes are
highlighted as the pointer hovers over them. When it’s True, the TreeView control behaves like
a web document with the nodes acting as hyperlinks — they turn blue while the pointer hovers
over them. Use the NodeMouseHover event to detect when the pointer hovers over a node.
Indent This property specifies the indentation level in pixels. The same indentation applies
to all levels of the tree — each level is indented by the same number of pixels with respect to its
parent level.
PathSeparator A node’s full name is made up of the names of its parent nodes separated by
a backslash. To use a different separator, set this property to the desired symbol.
ShowLines The ShowLines property is a True/False value that determines whether the con-
trol’s nodes will be connected to its parent items with lines. These lines help users visualize the
hierarchy of nodes, and it’s customary to display them.
ShowPlusMinus The ShowPlusMinus property is a True/False value that determines whether
the plus/minus button is shown next to the nodes that have children. The plus button is dis-
played when the node is collapsed, and it causes the node to expand when clicked. Likewise,
the minus sign is displayed when the node is expanded, and it causes the node to collapse
when clicked. Users can also expand the current node by pressing the left-arrow button and
collapse it with the right-arrow button.

ShowRootLines This is another True/False property that determines whether there will
be lines between each node and root of the tree view. Experiment with the ShowLines and
ShowRootLines properties to find out how they affect the appearance of the control.
Sorted This property determines whether the items in the control will be automatically
sorted. The control sorts each level of nodes separately. In our globe example, it will sort the
continents, then the countries within each continent, and then the cities within each country.
Adding Nodes at Design Time
Let’s look now at the process of populating the TreeView control. Adding an initial collection
of nodes to a TreeView control at design time is trivial. Locate the Nodes property in the Prop-
erties window, and you’ll see that its value is Collection. To add items, click the ellipsis button,
and the TreeNode Editor dialog box will appear, as shown in Figure 7.15. To add a root item,
just click the Add Root button. The new item will be named Node0 by default. You can change
its caption by selecting the item in the list and setting its Text property accordingly. You can
also change the node’s Name property, and you can change the node’s appearance by using the
NodeFont, FontColor,andForeColor properties.
THE TREEVIEW AND LISTVIEW CONTROLS 291
Figure 7.15
The TreeNode Editor
dialog box
Follow these steps to enter the root node with the string Globe, a child node for Europe, and
two more nodes under Europe: Germany and Italy. I’m assuming that you’re starting with a
clean control. If your TreeView control contains any items, clear them all by selecting one item
at a time in the list and pressing the Delete key, or click the delete button (the one with the X
icon) on the dialog box.
Click the Add Root button first to add the node Node0. Select it with the mouse, and its
properties appear in the right pane of the TreeNode Editor window. Here you can change the
node’s Text property to Globe. You can specify the appearance of each node by setting its font
and fore/background colors.
Then click the Add Child button, which adds a new node under the Globe root node. Select
it with the mouse as before, and change its Text property to Europe. Then select the newly

added node in the list and click the Add Child button again. Name the new node Germany.
You’ve successfully added a small hierarchy of nodes. To add another node under Europe,
select the Europe node in the list and click the Add Child button again. Name the new item
Italy. Continue adding a few cities under each country to complete the tree.
Click the OK button to close the TreeNode Editor’s window and return to your form. The
nodes you added to the TreeView control are there, but they’re collapsed. Only the root nodes
are displayed with the plus sign in front of their names. Click the plus sign to expand the tree
and see its child nodes. The TreeView control behaves the same at design time as it does at
runtime — as far as navigating the tree goes, at least.
Adding Nodes at Runtime
Adding items to the control at runtime is a bit more involved. All the nodes belong to the con-
trol’s Nodes collection, which is made up of TreeNode objects. To access the Nodes collection,
use the following expression, where TreeView1 is the control’s name and Nodes is a collection
of TreeNode objects:
TreeView1.Nodes
292 CHAPTER 7 MORE WINDOWS CONTROLS
This expression returns a collection of TreeNode objects and exposes the proper members for
accessing and manipulating the individual nodes. The control’s Nodes property is the collection
of all root nodes.
The following statements print the strings shown highlighted below them (these strings are
not part of the statements; they’re the output that the statements produce):
Debug.WriteLine(TreeView1.Nodes(0).Text)
Globe
Debug.WriteLine(TreeView1.Nodes(0).Nodes(0).Text)
Europe
Debug.WriteLine(TreeView1.Nodes(0).Nodes(0).Nodes(1).Text)
Italy
Adding New Nodes
To add a new node to the Nodes collection use the Add method, which accepts as an argument
a string or a TreeNode object, and returns a TreeNode object that represents the newly added

node. The simplest form of the Add method is
newNode = Nodes.Add(nodeCaption)
where nodeCaption is a string that will be displayed on the control. Another form of the Add
method allows you to add a TreeNode object directly (nodeObj is a properly initialized Tree-
Node variable):
newNode = Nodes.Add(nodeObj)
To use this form of the method, you must first declare and initialize a TreeNode object:
Dim nodeObj As New TreeNode
nodeObj.Text = "Tree Node"
nodeObj.ForeColor = Color.BlueViolet
TreeView1.Nodes.Add(nodeObj)
The last overloaded form of the Add method allows you to specify the index in the current
Nodes collection, where the node will be added:
newNode = Nodes.Add(index, nodeObj)
The nodeObj TreeNode object must be initialized as usual.
To add a child node to the root node, use a statement such as the following:
TreeView1.Nodes(0).Nodes.Add("Asia")
To add a country under Asia, use a statement such as the following:
TreeView1.Nodes(0).Nodes(1).Nodes.Add("Japan")
THE TREEVIEW AND LISTVIEW CONTROLS 293
The expressions can get quite lengthy. The proper way to add child items to a node is to
create a TreeNode variable that represents the parent node, under which the child nodes will
be added. Let’s say that the ContinentNode variable in the following example represents the
node Europe:
Dim ContinentNode As TreeNode
ContinentNode = TreeView1.Nodes(0).Nodes(2)
Then you can add child nodes to the ContinentNode node:
ContinentNode.Nodes.Add("France")
ContinentNode.Nodes.Add("Germany")
To add yet another level of nodes, the city nodes, create a new variable that represents a

specific country. The Add method actually returns a TreeNode object that represents the newly
added node, so you can add a country and a few cities by using statements such as the following:
Dim CountryNode As TreeNode
CountryNode = ContinentNode.Nodes.Add("Germany")
CountryNode.Nodes.Add("Berlin")
CountryNode.Nodes.Add("Frankfurt")
The ListView Control
The ListView control is similar to the ListBox control except that it can display its items in
many forms, along with any number of subitems for each item. To use the ListView control in
your project, place an instance of the control on a form and then set its basic properties, which
are described in the following list:
View and Alignment Two properties determine how the various items will be displayed on
the control: the View property, which determines the general appearance of the items, and the
Alignment property, which determines the alignment of the items on the control’s surface. The
View property can have one of the values shown in Table 7.3.
Table 7.3: View property settings
Setting Description
LargeIcon (Default) Each item is represented by an icon and a caption below the icon.
SmallIcon Each item is represented by a small icon and a caption that appears to the right of
the icon.
List Each item is represented by a caption.
Details Each item is displayed in a column with its subitems in adjacent columns.
Tile Each item is displayed with an icon and its subitems to the right of the icon. This
view is available only on Windows XP and Windows Server 2003.
294 CHAPTER 7 MORE WINDOWS CONTROLS
The Alignment property can have one of the settings shown in Table 7.4.
Table 7.4: Alignment property settings
Setting Description
Default When an item is moved on the control, the item remains where it is dropped.
Left Items are aligned to the left side of the control.

SnapToGrid Items are aligned to an invisible grid on the control. When the user moves an item,
the item moves to the closest grid point on the control.
Top Items are aligned to the top of the control.
HeaderStyle This property determines the style of the headers in Details view. It has no
meaning when the View property is set to anything else because only the Details view has
columns. The possible settings of the HeaderStyle property are shown in Table 7.5.
Table 7.5: HeaderStyle property settings
Setting Description
Clickable Visible column header that responds to clicking
Nonclickable (Default) Visible column header that does not r espond to clicking
None No visible column header
AllowColumnReorder This property is a True/False value that determines whether the user
can reorder the columns at runtime, and it’s meaningful only in Details view. If this property
is set to True, the user can move a column to a new location by dragging its header with the
mouse and dropping it in the place of another column.
Activation This property, which specifies how items are activated with the mouse, can have
one of the values shown in Table 7.6.
Table 7.6: Activation property settings
Setting Description
OneClick Items are activated with a single click. When the cursor is over an item, it changes
shape and the color of the item’s text changes.
Standard (Default) Items are activated with a double-click. No change in the selected item’s
text color takes place.
TwoClick Items are activated with a double-click and their text changes color as well.
THE TREEVIEW AND LISTVIEW CONTROLS 295
FullRowSelect This property is a True/False value, indicating whether the user can select an
entire row or just the item’s text, and it’s meaningful only in Details view. When this property
is False, only the first item in the selected row is highlighted.
GridLines Another True/False property. If it’s True, grid lines between items and subitems
are drawn. This property is meaningful only in Details view.

Groups The items of the ListView control can be grouped into categories. To use this feature,
you must first define the groups by using the control’s Groups property, which is a collection
of strings. You can add as many members to this collection as you want. After that, as you add
items to the ListView control, you can specify the group to which they belong. The control will
group the items of the same category together and display the group title above each group.
You can easily move items between groups at runtime by setting the Groups property for the
corresponding item to the name of the desired group.
LabelEdit The LabelEdit property lets you specify whether the user will be allowed to edit
the text of the items. The default value of this property is False. Notice that the LabelEdit
property applies to the item’s Text property only; you can’t edit the subitems (unfortunately,
you can’t use the ListView control as an editable grid).
MultiSelect A True/False value, indicating whether the user can select multiple items from
the control. To select multiple items, click them with the mouse while holding down the Shift
or Ctrl key. If the control’s ShowCheckboxes property is set to True, users can select multiple
items by marking the check box in front of the corresponding item(s).
Scrollable A True/False value that determines whether the scroll bars are visible. Even
if the scroll bars are invisible, users can still bring any item into view. All they have to do is
select an item and then press the arrow keys as many times as needed to scroll the desired item
into view.
Sorting This property determines how the items will be sorted, and its setting can be None,
Ascending, or Descending. To sort the items of the control, call the Sort method, which sorts
the items according to their caption. It’s also possible to sort the items according to any of their
subitems, as explained later in this chapter.
The Columns Collection
To display items in Details view, you must first set up the appropriate columns. The first
column corresponds to the item’s caption, and the following columns correspond to its
subitems. If you don’t set up at least one column, no items will be displayed in Details view.
Conversely, the Columns collection is meaningful only when the ListView control is used in
Details view.
The items of the Columns collection are of the ColumnHeader type. The simplest way to set

up the appropriate columns is to do so at design time by using a visual tool. Locate and select
the Columns property in the Properties window, and click the ellipsis button next to the prop-
erty. The ColumnHeader Collection Editor dialog box, shown in Figure 7.16, will appear, and
you can use it to add and edit the appropriate columns.
Adding columns to a ListView control and setting their properties through the dialog
box shown in Figure 7.16 is quite simple. Don’t forget to size the columns according to the data
you anticipate storing in them and to set their headers. You can also add columns from within
your code at runtime, a topic that’s discussed in the tutorial ‘‘The ListView and TreeView
Controls,’’ available for download from www.sybex.com/go/masteringvb2010.
296 CHAPTER 7 MORE WINDOWS CONTROLS
Figure 7.16
The ColumnHeader
Collection Editor
dialog box
ListView Items and Subitems
As with the TreeView control, the ListView control can be populated either at design time or at
runtime. To add items at design time, click the ellipsis button next to the ListItems property
in the Properties window. When the ListViewItem Collection Editor dialog box pops up, you
can enter the items, including their subitems, as shown in Figure 7.17.
Figure 7.17
The ListViewItem
Collection Editor
dialog box
Click the Add button to add a new item. Each item has subitems, which you can specify as
members of the SubItems collection. To add an item with three subitems, you must populate
the item’s SubItems collection with the appropriate elements. Click the ellipsis button next to
the SubItems property in the ListViewItem Collection Editor; the ListViewSubItem Collection
THE TREEVIEW AND LISTVIEW CONTROLS 297
Editor will appear. This dialog box is similar to the ListViewItem Collection Editor dialog box,
and you can add each item’s subitems. Assuming that you have added the item called Item 1

in the ListViewItem Collection Editor, you can add these subitems: Item 1-a, Item 1-b,and
Item 1-c. The first subitem (the one with zero index) is actually the main item of the control.
Notice that you can set other properties such as the color and font for each item, the check
box in front of the item that indicates whether the item is selected, and the image of the item.
Use this window to experiment with the appearance of the control and the placement of the
items, especially in Details view because subitems are visible only in this view. Even then, you
won’t see anything unless you specify headers for the columns. Note that you can add more
subitems than there are columns in the control. Some of the subitems will remain invisible.
Unlike the TreeView control, the ListView control allows you to specify a different appear-
ance for each item and each subitem. To set the appearance of the items, use the Font, Back-
Color,andForeColor properties of the ListViewItem object.
The Items Collection
All the items on the ListView control form a collection: the Items collection. This collection
exposes the typical members of a collection that let you manipulate the control’s items. These
members are discussed next.
Add method This method adds a new item to the Items collection. The syntax of the Add
method is as follows:
ListView1.Items.Add(caption)
You can also specify the index of the image to be used, along with the item and a collection
of subitems to be appended to the new item, by using the following form of the Add method,
where imageIndex is the index of the desired image on the associated ImageList control:
ListView1.Items.Add(caption, imageIndex)
Finally, you can create a ListViewItem object in your code and then add it to the ListView con-
trol by using the following form of the Add method:
ListView1.Items.Add(listItemObj)
The following statements create a new item, set its individual subitems, and then add the
newly created ListViewItem object to the control:
Dim LItem As New ListViewItem
LItem.Text = "new item"
LItem.SubItems.Add("sub item 1a")

LItem.SubItems.Add("sub item 1b")
LItem.SubItems.Add("sub item 1c")
ListView1.Items.Add(LItem)
Count property Returns the number of items in the collection.
Item property Retrieves an item specified by an index value.
Clear method Removes all the items from the collection.
Remove method Removes an item from the collection.
298 CHAPTER 7 MORE WINDOWS CONTROLS
The SubItems Collection
Each item in the ListView control may have one or more subitems. You can think of the item
as the key of a record and the subitems as the other fields of the record. The subitems are dis-
played only in Details mode, but they are available to your code in any view. For example, you
can display all items as icons and, when the user clicks an icon, show the values of the selected
item’s subitems on other controls.
To access the subitems of a given item, use its SubItems collection. The following statements
add an item and three subitems to the ListView1 control:
Dim LItem As ListViewItem
LItem = ListView1.Items.Add("Alfred’s Futterkiste")
LItem.SubItems.Add("Maria Anders")
LItem.SubItems.Add("030-0074321")
LItem.SubItems.Add("030-0076545")
To access the SubItems collection, you need a reference to the item to which the subitems
belong. The Add method returns a reference to the newly added item, the LItem variable, which
is then used to access the item’s subitems, as shown in the preceding code segment.
Displaying the subitems on the control requires some overhead. Subitems are displayed only
in Details view mode. However, setting the View property to Details is not enough. You must
first create the columns of the Details view, as explained earlier. The ListView control displays
only as many subitems as there are columns in the control. The first column, with the header
Company, displays the items of the list. The following columns display the subitems. More-
over, you can’t specify which subitem will be displayed under each header. The first subitem

(Maria Anders in the preceding example) will be displayed under the second header, the sec-
ond subitem (030-0074321 in the same example) will be displayed under the third header, and
so on. At runtime, the user can rearrange the columns by dragging them with the mouse. To
disable the rearrangement of the columns at runtime, set the control’s AllowColumnReorder
property to False (its default value is True).
Unless you set up each column’s width, they will all have the same width. The width of
individual columns is specified in pixels, and you can set it to a percentage of the total width
of the control, especially if the control is docked to the form. The following code sets up a
ListView control with four headers, all having the same width:
Dim LWidth = ListView1.Width - 5
Dim headers =
{
New ColumnHeader() With {.Text = "Company", .Width = LWidth / 4},
New ColumnHeader() With {.Text = "Contact", .Width = LWidth / 4},
New ColumnHeader() With {.Text = "Phone", .Width = LWidth / 4},
New ColumnHeader() With {.Text = "Fax", .Width = LWidth / 4}
}
ListView1.Columns.AddRange(headers)
ListView1.View = View.Details
The first header corresponds to the item (not a subitem). The number of headers you set up
must be equal to the number of subitems you want to display on the control, plus one. The
constant 5 is subtracted to compensate for the width of the column separators. If the control
THE TREEVIEW AND LISTVIEW CONTROLS 299
is anchored to the vertical edges of the form, you must execute these statements from within
the form’s Resize event handler so that the columns are resized automatically as the control is
resized.
You can also sort a ListView control with the Sort method, which sorts the list’s items, and
the Sorting property, which determines how the items will be sorted. For more information on
sorting the control’s items, see the tutorial ‘‘The ListView and TreeView Controls,’’ available for
download from www.sybex.com/go/masteringvb2010.

Processing Selected Items
The user can select multiple items from a ListView control by default. Even though you can
display a check mark in front of each item, it’s not customary. Multiple items in a ListView
control are selected with the mouse while holding down the Ctrl or Shift key.
The selected items form the SelectedListItemCollection collection, which is a property
of the control. You can iterate through this collection with a For … Next loop or through the
enumerator object exposed by the collection. Listing 7.17 is the code behind the Selected Items
button of the ListViewDemo project. It goes through the selected items with a For Each … Next
loop and displays each one of them, along with its subitems, in the Output window. Notice
that you can select multiple items in any view, even when the subitems are not visible. They’re
still there, however, and they can be retrieved through the SubItems collection.
Listing 7.17: Iterating the selected items on a ListView control
Private Sub bttnIterate_Click(…) Handles bttnIterate.Click
Dim LItem As ListViewItem
Dim LItems As ListView.SelectedListViewItemCollection
LItems = ListView1.SelectedItems
For Each LItem In LItems
Debug.Write(LItem.Text & vbTab)
Debug.Write(LItem.SubItems(0).ToString & vbTab)
Debug.Write(LItem.SubItems(1).ToString & vbTab)
Debug.WriteLine(LItem.SubItems(2).ToString & vbTab)
Next
End Sub
VB 2010 at Work: The CustomExplorer Project
To demonstrate how to use the ListView and TreeView controls in tandem, which is how they
commonly used, see the discussion of the CustomExplorer sample application, which is dis-
cussed in the tutorial ‘‘The ListView and TreeView controls.’’ It’s a fairly advanced example,
but I included it for the most ambitious readers. It can also be used as the starting point for
many custom applications, so give it a try.
The CustomExplorer project, shown in Figure 7.18, displays a structured list of folders in the

left pane and the files in the selected folder in the right pane. The left pane is populated when
the application starts. You can expand any folder in this pane and view its subfolders. To view
the files in a folder, click the folder name and the right pane will be populated with the names
of the selected folder’s files along with other data, such as the file size, date of creation, and
date of last modification.
300 CHAPTER 7 MORE WINDOWS CONTROLS
Figure 7.18
The CustomExplorer
project demonstrates
how to combine
a TreeView a nd a
ListView control on the
same form.
The CustomExplorer project is not limited to displaying folders and files; you can populate
the two controls with data from several sources. For example, you can display customers in the
left pane (and organize them by city or state) and display their related data, such as invoices
and payments, in the right pane. Or you can populate the left pane with product names and
the right pane with the respective sales. In general, you can use the project as an interface for
many types of applications. You can even use it as a custom Explorer to add features that are
specific to your applications.
The Bottom Line
Use the OpenFileDialog and SaveFileDialog controls to prompt users for filenames.
Windows applications use certain controls to prompt users for common information, such as
filenames, colors, and fonts. Visual Studio provides a set of controls that are grouped in the
Dialogs section of the Toolbox. All common dialog controls provide a ShowDialog method,
which displays the corresponding dialog box in a modal way. The ShowDialog method returns
a value of the DialogResult type, which indicates how the dialog box was closed, and you
should examine this value before processing the data.
Master It Your application needs to open an existing file. How will you prompt users for
the file’s name?

Master It You’re developing an application that encrypts multiple files (or resizes many
images) in batch mode. How will you prompt the user for the files to be processed?
Use the ColorDialog and FontDialog controls to prompt users for colors and typefaces. The
Color and Font dialog boxes allow you to prompt users for a color value and a font, respec-
tively. Before showing the corresponding dialog box, set its Color or Font property according
to the current selection, and then call the control’s ShowDialog method.
THE BOTTOM LINE 301
Master It How will you display color attributes in the Color dialog box when you open it?
How will you display the attributes of the selected text’s font in the Font dialog box when
you open it?
Use the RichTextBox control as an advanced text editor to present richly formatted text.
The RichTextBox control is an enhanced TextBox control that can display multiple fonts and
styles, format paragraphs with different styles, and provide a few more-advanced text-editing
features. Even if you don’t need the formatting features of this control, you can use it as an
alternative to the TextBox control. At the very least, the RichTextBox control provides more
editing features, a more-useful undo function, and more-flexible search features.
Master It You want to display a document with a title in large, bold type, followed by a
couple of items in regular style. Which statements will you use to create a document like
this on a RichTextBox control?
Document’s Title
Item 1 Description for item 1
Item 2 Description for item 2
Create and present hierarchical lists by using the TreeView control. The TreeView con-
trol is used to display a list of hierarchically structured items. Each item in the TreeView con-
trol is represented by a TreeNode object. To access the nodes of the TreeView control, use the
TreeView.Nodes collection. The nodes under a specific node (in other words, the child nodes)
form another collection of Node objects, which you can access by using the expression Tree-
View.Nodes(i).Nodes. The basic property of the Node object is the Text property, which
stores the node’s caption. The Node object exposes properties for manipulating its appearance
(its foreground/background color, its font, and so on).

Master It How will you set up a TreeView control with a book’s contents at design time?
Create and present lists of structured items by using the ListView control. The ListView
control stores a collection of ListViewItem objects, which form the Items collection, and can dis-
play them in several modes, as specified by the View property. Each ListViewItem object has a
Text property and the SubItems collection. The subitems are not visible at runtime unless you
set the control’s View property to Details and set up the control’s Columns collection. There
must be a column for each subitem you want to display on the control.
Master It How will you set up a ListView control with three columns to display names,
email addresses, and phone numbers at design time?
Master It How would you populate the same control with the same data at runtime?

Part 3
Working with Custom
Classes and Controls
◆ Chapter 8: Working with Objects
◆ Chapter 9: Building Custom Windows Controls
◆ Chapter 10: Applied Object-Oriented Programming

Chapter 8
Working with Objects
Classes are practically synonymous with objects and they’re at the very heart of programming
with Visual Basic. The controls you use to build the visible interface of your application are
objects, and the process of designing forms consists of setting the properties of these objects,
mostly with point-and-click operations. The Framework itself is an enormous compendium of
classes, and you can import any of them into your applications and use them as if their mem-
bers were part of the language. You simply declare a variable of the specific class type, initialize
it, and then use it in your code.
Controls are also objects; they differ from other classes in that controls provide a visual
interface, whereas object variables don’t. However, you manipulate all objects by setting their
properties and calling their methods.

In this chapter, you’ll learn how to do the following:
◆ Build your own classes
◆ Use custom classes in your projects
◆ Customize the usual operators for your classes
Classes a nd Objects
When you create a variable of any type, you’re creating an instance of a class. The variable
lets you access the functionality of the class through its properties and methods. Even
base data types are implemented as classes (the System.Integer class, System.Double, and
so on). An integer value, such as 3, is an instance of the System.Integer class, and you
can call the properties and methods of this class by using its instance. Expressions such
as Convert.ToDecimal(3).MinValue and #1/1/2000#.Today are odd but valid. The first
expression returns the minimum value you can represent with the Decimal data type, whereas
the second expression returns the current date. The DataTime data type exposes the Today
property, which returns the current date. The expression #1/1/2000# is a value of the
DataTime type, so you can find out the current date by calling its Today property. If you enter
either one of the preceding expressions in your code, you’ll get a warning, but they will be
executed.
Classes are used routinely in developing applications, and you should get into the habit of
creating and using custom classes, even with simple projects. In team development, classes are
a necessity because they allow developers to share their work easily. If you’re working in a cor-
porate environment, where different programmers code different parts of an application, you
306 CHAPTER 8 WORKING WITH OBJECTS
can’t afford to repeat work that someone else has already done. You should be able to get their
code and use it in your application as is. That’s easier said than done because you can guess
what will happen as soon as a small group of programmers start sharing code — they’ll end
up with dozens of different versions for each function, and every time a developer upgrades a
function, they will most likely break the applications that were working with the old version.
Or each time they revise a function, they must update all the projects by using the old version
of the function and test them. It just doesn’t work.
The major driving force behind object-oriented programming (OOP) is code reuse. Classes

allow you to write code that can be reused in multiple projects. You already know that classes
don’t expose their source code. The Framework itself is a huge collection of classes, which
you can use without ever seeing its source code. As you’ll learn in Chapter 10, ‘‘Applied
Object-Oriented Programming,’’ you can even expand the functionality of an existing class
without having access to its code. In other words, you can use a class without having access to
its code, and therefore you can’t affect any other projects that use the class. You also know that
classes implement complicated operations and make these operations available to programmers
through properties and methods. The Array class, for example, exposes a Sort method, which
sorts its elements. This is not a simple operation, but fortunately you don’t have to know
anything about sorting. Someone else has done it for you and made this functionality available
to your applications. This is called encapsulation. Some functionality has been built into the
class (or encapsulated into the class), and you can access it from within your applications by
using a simple method call. The System.Security.Cryptography class of the Framework (which
isn’t discussed in this book) provides all the functionality you need to encrypt a secret code,
or an entire document, by calling a method. Encryption is a very complicated operation, but
you don’t have to know anything about it except how to call the appropriate method and pass
a secret key to it.
What Is a Class?
A class can be thought of as a program that doesn’t run on its own; it’s a collection of prop-
erties and methods that must be used by another application. We exploit the functionality of
the class by creating a variable of the same type as the class and then calling the class’s proper-
ties and methods through this variable. The methods and properties of the class, as well as its
events, constitute the class’s interface. It’s not a visible interface, like the ones you’ve learned to
design so far, because the class doesn’t interact directly with the user. To interact with the class,
the application uses the class’s interface, just as users will be interacting with your application
through its visual interface.
You have already learned how to use classes. Now is the time to understand what goes on
behind the scenes when you interact with a class and its members. Every object is an instance
of a class. When you declare an array, a Color object, or a collection, some code is executed in
the background to create the variable. It’s the code that actually implements the class. When

you declare an array, you’re invoking the System.Array class, which contains all the code for
manipulating arrays (the method to sort the array’s elements, another method to reverse the
order of the elements in the array, and so on). Even simple variables of the Integer or String
type are implemented as classes.
The first time you use an object in your code, you’re instantiating the class that implements
it. The class’s code is loaded into memory, initializes its variables, and is ready to execute. The
image of the class in memory is said to be an instance of the class, and this is an object.
WHAT IS A CLASS? 307
Classes versus Objects
Two of the most misused terms in OOP are object and class, and most people use them
interchangeably. You should think of the class as the template for the object. There’s only
one System.Array class, but you can declare any number of arrays in your code. Every array
is an instance of the System.Array class. All arrays in an application are implemented by the
same code, but they store different data. Each instance of a class is nothing more than a set
of variables: The same code acts on different sets of variables, and each set of variables is a
separate and distinct instance of the class.
Consider three TextBox controls on the same form. They are all instances of the Sys-
tem.Windows.Forms.TextBox class, but changing any property of a TextBox control doesn’t
affect the other two controls. Every time you set the Text property of a TextBox control,
you’re modifying a variable of a specific instance of the TextBox class. Classes are the
blueprints on which objects are based. You can use the same blueprint to build multiple
buildings with the same structural characteristics but apply different properties (wall colors,
doors, and so on) to individualize each structure.
Objects are similar to Windows controls except that they don’t have a visible interface. Con-
trols are instantiated when the form loads. To use a control, you make it part of the project by
adding its icon to the Toolbox, if it’s not already there. To manipulate a control from within
your code, you call its properties and methods. You do the same with classes. To use a class,
first declare it, then instantiate it (most commonly by using a New statement), then use its
properties and methods. Finally, you program the various events raised by the controls to
interact with the users of your applications. Most classes don’t expose any events because the

user can’t interact with them, but some classes do raise events, which you can program just
as you program the events of Windows controls.
At the beginning of this section I mentioned that classes can be thought of as ‘‘programs that
can’t be executed on their own.’’ This is an oversimplification, which I can remedy now. Classes
are made up of code, not visual elements, and are used as templates for objects. For example,
there’s a single System.Array class and this class is invoked every time you create an array in
your code. The arrays you declare in your code are instances of the class. Yet, there’s only one
class that implements arrays and all arrays are ‘‘serviced’’ by the same class.
Classes Combine Code with Data
Another way to view classes is to understand how they combine code and data. This simple
idea is the very essence of object-oriented programming. Data is data, and procedural lan-
guages allow you to manipulate data in any way. Meaningful data, however, is processed in
specific ways.
Let’s consider accounting data. You can add or subtract amounts to or from an account,
sum similar accounts (such as training and travel expenses), calculate taxes on certain account
amounts, and the like. Other types of processing may not be valid for this type of data. You
never multiply the amounts from two different accounts or calculate logarithms of account
balances. These types of processing are quite meaningful with different data, but not with
accounting data.
Because the nature of the data itself determines to a large extent the type of processing that
will take place on the data, why not ‘‘package’’ the data along with the code for processing it?

×