Visual Basic 2005 for Programmers (2nd Edition)

14.10. ListView Control

The ListView control is similar to a ListBox in that both display lists from which the user can select one or more items (an example of a ListView can be found in Fig. 14.31). The important difference between the two classes is that a ListView can display icons next to the list items (controlled by its ImageList property). Property MultiSelect (a Boolean) determines whether multiple items can be selected. CheckBoxes can be included by setting property CheckBoxes (a Boolean) to true, making the ListView similar in appearance to a CheckedListBox. The View property specifies the layout of the ListBox. Property Activation determines the method by which the user selects a list item. Figure 14.29 presents some of the ListView class's common properties and its ItemActivate event.

Figure 14.29. ListView properties and an event.

ListView properties and an even

Description

Common Properties

Activation

Determines how the user activates an item. This property takes a value in the ItemActivation enumeration. Possible values are OneClick (single-click activation), TwoClick (double-click activation, item changes color whenselected) and Standard (double-click activation, item does not change color).

CheckBoxes

Indicates whether items appear with CheckBoxes. true displays CheckBoxes. The default is False.

LargeImageList

Specifies the ImageList containing large icons for display.

Items

Returns the collection of ListViewItems in the control.

MultiSelect

Determines whether multiple selection is allowed. The default is true, which enables multiple selection.

SelectedItems

Gets the collection ofselected items.

SmallImageList

Specifies the ImageList containing small icons for display.

View

Determines appearance of ListViewItems. Possible values are LargeIcon (large icon displayed, items can be in multiple columns), SmallIcon (small icon displayed, items can be in multiple columns), List (small icons displayed, items appear in a single column), Details (like List, but multiple columns of information can be displayed per item) and Tile (large iconsdisplayed, information provided to right of icon, valid only in Windows XP or later).

Common Event

ItemActivate

Generated when an item in the ListView is activated. Does not containthe specifics of the item activated.

ListView allows you to define the images used as icons for ListView items. To display images, an ImageList component is required. Create one by dragging it to a Form from the ToolBox. Then select the Images property in the Properties window to display the Image Collection Editor (Fig. 14.30). Here you can browse for images that you wish to add to the ImageList, which contains an array of Images. Once the images have been defined, set property SmallImageList of the ListView to the new ImageList object. Property SmallImageList specifies the image list for the small icons. Property LargeImageList sets the ImageList for large icons. The items in a ListView are each of type ListViewItem. Icons for the ListView items are selected by setting the item's ImageIndex property to the appropriate index.

Figure 14.30. Image Collection Editor window for an ImageList component.

Class FrmListViewTest (Fig. 14.31) displays files and folders in a ListView, along with small icons representing each file or folder. If a file or folder is inaccessible because of permission settings, a MessageBox appears. The program scans the contents of the directory as it browses, rather than indexing the entire drive at once.

Figure 14.31. ListView displaying files and folders.

1 ' Fig. 14.31: FrmListViewTest.vb 2 ' Displaying directories and their contents in ListView. 3 Imports System.IO 4 5 Public Class FrmListViewTest 6 ' store current directory 7 Private currentDirectory As String = Directory.GetCurrentDirectory() 8 9 ' display files/subdirectories of current directory 10 ' (i.e., the one from which the application is executed) 11 Private Sub FrmListViewTest_Load(ByVal sender As Object, _ 12 ByVal e As System.EventArgs) Handles Me.Load 13 ' set Image list 14 Dim folderImage As Image = Image.FromFile( _ 15 currentDirectory & "\images\folder.bmp") 16 17 Dim fileImage As Image = Image.FromFile( _ 18 currentDirectory & "\images\file.bmp") 19 20 fileFolder.Images.Add(folderImage) 21 fileFolder.Images.Add(fileImage) 22 23 ' load current directory into browserListView 24 LoadFilesInDirectory(currentDirectory) 25 lblDisplay.Text = currentDirectory 26 End Sub ' FrmListViewTest_Load 27 28 ' browse directory user clicked or go up one level 29 Private Sub lvwBrowser_Click(ByVal sender As System.Object, _ 30 ByVal e As System.EventArgs) Handles lvwBrowser.Click 31 ' ensure an item is selected 32 If lvwBrowser.SelectedItems.Count <> 0 Then 33 ' if first item selected, go up one level 34 If lvwBrowser.Items( 0 ).Selected Then 35 ' create DirectoryInfo object for directory 36 Dim directoryObject As DirectoryInfo = _ 37 New DirectoryInfo(currentDirectory) 38 39 ' if directory has parent, load it 40 If directoryObject.Parent IsNot Nothing Then 41 LoadFilesInDirectory(directoryObject.Parent.FullName) 42 lblDisplay.Text = currentDirectory 43 End If 44 Else ' selected directory or file 45 ' directory or file chosen 46 Dim chosen As String = lvwBrowser.SelectedItems( 0 ).Text 47 48 ' if item selected is directory, load selected directory 49 If Directory.Exists(currentDirectory & "\" & chosen) Then 50 ' if currently in C:\, do not need '\'; otherwise we do 51 If currentDirectory = "C:\" Then 52 LoadFilesInDirectory(currentDirectory & chosen) 53 Else 54 LoadFilesInDirectory(currentDirectory & "\" & chosen) 55 End If 56 57 ' update displayLabel 58 lblDisplay.Text = currentDirectory 59 End If 60 End If 61 End If 62 End Sub ' lvwBrowser_Click 63 64 ' display files/subdirectories of current directory 65 Private Sub LoadFilesInDirectory( _ 66 ByVal currentDirectoryValue As String) 67 ' load directory information and display 68 Try 69 ' clear ListView and set first item 70 lvwBrowser.Items.Clear() 71 lvwBrowser.Items.Add("Go Up One Level") 72 73 ' update current directory 74 currentDirectory = currentDirectoryValue 75 Dim newCurrentDirectory As DirectoryInfo = _ 76 New DirectoryInfo(currentDirectory) 77 78 ' put files and directories into arrays 79 Dim directoryArray As DirectoryInfo() = _ 80 newCurrentDirectory.GetDirectories() 81 Dim fileArray As FileInfo() = newCurrentDirectory.GetFiles() 82 83 ' add directory names to ListView 84 For Each dir As DirectoryInfo In directoryArray 85 ' add directory to ListView 86 Dim newDirectoryItem As ListViewItem = _ 87 lvwBrowser.Items.Add(dir.Name) 88 89 newDirectoryItem.ImageIndex = 0 ' set directory image 90 Next 91 92 ' add file names to ListView 93 For Each file As FileInfo In fileArray 94 ' add file to ListView 95 Dim newFileItem As ListViewItem = _ 96 lvwBrowser.Items.Add(file.Name) 97 98 newFileItem.ImageIndex = 1 ' set file image 99 Next 100 Catch e As UnauthorizedAccessException 101 MessageBox.Show( "Warning: Some files may not be " & _ 102 "visible due to permission settings", _ 103 "Attention", 0, MessageBoxIcon.Warning) 104 End Try 105 End Sub ' LoadFilesInDirectory 106 End Class ' FrmListViewTest

(a)

(b)

(c)

To display icons beside list items, create an ImageList for the ListView lvwBrowser. First, drag and drop an ImageList on the Form and open the Image Collection Editor. Select our two simple bitmap images, provided in the bin\Debug and bin\Release folders of this exampleone for a folder (array index 0) and the other for a file (array index 1). Then set the object lvwBrowser property SmallImageList to the new ImageList in the Properties window.

Method LoadFilesInDirectory (lines 65105) populates lvwBrowser with the directory passed to it (currentDirectoryValue). It clears lvwBrowser and adds the element "Go Up One Level". When the user clicks this element, the program attempts to move up one level (we see how shortly). The method then creates a DirectoryInfo object initialized with the String currentDirectory (lines 7576). If you do not have permission to browse the directory, an exception is thrown (and caught in line 100). Method LoadFilesInDirectory works differently from method PopulateTreeView in the previous program (Fig. 14.28). Rather than loading the names of all the folders on the hard drive, method LoadFilesInDirectory loads only the names of folders in the current directory. In this example, we also load the names of the files in the current directory.

Class DirectoryInfo (namespace System.IO) makes it easy to browse or manipulate the directory structure. Method Getdirectories (line 80) returns an array of DirectoryInfo objects containing the subdirectories of the current directory. Similarly, method GetFiles (line 81) returns an array of class FileInfo objects containing the files in the current directory. Property Name (of both class DirectoryInfo and class FileInfo) contains only the directory or file name, such as temp instead of C:\myfolder\temp. To access the full name and location, use property FullName.

Lines 8490 and lines 9399 iterate through the subdirectories and files of the current directory and add them to lvwBrowser. Lines 89 and 98 set the ImageIndex properties of the newly created items. If an item is a directory, we set its icon to a directory icon (index 0); if an item is a file, we set its icon to a file icon (index 1).

Method lvwBrowser_Click (lines 2962) responds when the user clicks control lvwBrowser. Line 32 checks whether anything is selected. If a selection has been made, line 34 determines whether the user chose the first item in lvwBrowser. The first item in lvwBrowser is always Go Up One Level; if it is selected, the program attempts to go up a level. Lines 3637 create a DirectoryInfo object for the current directory. Line 40 tests property Parent to ensure that the user is not at the root of the directory tree. Property Parent indicates the parent directory as a DirectoryInfo object; if no parent directory exists, Parent returns the value Nothing. If a parent directory does exist, then line 41 passes the full name of the parent directory to method LoadFilesInDirectory, and line 42 displays the new current directory's name.

If the user did not select the first item in lvwBrowser, lines 4460 allow the user to continue navigating through the directory structure. Line 46 creates String chosen and assigns it the text of the selected item (the first item in collection SelectedItems). Line 49 determines whether the user selected a valid directory (rather than a file). The program combines variables currentDirectory and chosen (the new directory), separated by a backslash (\), and passes this value to class Directory's method Exists. Method Exists returns true if its String parameter is a directory. In this case, the program passes the directory's name to method LoadFilesInDirectory. If the current directory is C:\, a backslash is not needed to separate currentDirectory and chosen (line 52). However, other directories must be separated by a backslash (line 54). Finally, lblDisplay is updated with the new directory (line 58).

This program loads quickly, because it displays the names of only the directories and files in the current directory. This means that a small delay may occur each time you choose another directory. However, changes that occur in the directory structure while this program executes will appear when you reload a directory. The previous program (Fig. 14.28) may have a large initial delay as it loads an entire directory structure, but the program displays directory contents with no delay once the directory structure is loaded. Also, that program does not dynamically show directory structure changesyou would need to execute the program again. Trade-offs of this kind are typical in the software world.

Software Engineering Observation 14.2

When designing applications that run for long periods of time, you might choose a large initial delay to improve performance throughout the rest of the program. However, in applications that run for only short periods, developers often prefer fast initial loading times and small delays after each action.

Категории