Sorting and Searching

The ListView control provides the mechanisms for sorting its ms and searching for specific items, To sort the ListItems in the’ control, you. must assign the value True to the Sorted property. This is a Boolean value that determines whether the Listltems in the collectipn will be sorted. Two related properties a.rethe So~er . and SortKey properties. The SortOrder property determines whether the Listltems are sorted in ascending or descending order, and the SortKey property determines the sorting key. USortKey is 0, the list is sorted according to the item’s Text property. . If you want to sort the list according to a subitem, assign the subitem’s Index value . to the SortKey property.

The SortOrder property’s values are listed in Table.

It’s common to sort a list when the column header is clicked. For this reason, the SortKey property is commonly set from within the ColumnClick event to sort the list using the clicked column, as determined by the sort key and demonstrated in the following example:

The FindItem method finds and returns a reference to a ListItem object. You can . use this reference in your code to manipulate the properties of the found item. The syntax of the FindItem method is:

Findltem string. value. index. match

The smng argument is the search argument (the value being searched). The Find- Item method can search for a string in the Listltem objects’ Text and Tag properties, or in the SubItems collection. Value is an optional argument, which sped files where the search will take place, and its possible values are shown in Table.

in.4tx another optional sent, whit;h specifies where the search ~ begin. To search for an Listlm\after the 10th item in the list, set the index argument of the Fin4Itein method 10 11.115 default value is 1 (the first item in the CXlIltml).

The last argument, mtltch, is another optional argwnent that specifies how the specified seMch argument will be matched. It can have one of the values in Table.

The last button of the listViewDemo application searches the list for specific items .using the control’s FindItem method. When you click the Find Item button, you’ll be prompted to enter a string to search for. The code will search among the Listltems’ Text properties to locate the desired string. The following statement locates .he Findltem string among the items’ Text properties:

Set LItem = ListViewl.Findltem(Findltem, lvwText , ,  lvwPartial)

If the string isn’t found in any Listltem object’s Text property, the Litem variable is Nothing. In this case, the program will attempt to locate the same string in the subitems with the statement:

If LItem Is Nothing,Then .Set LItem· ListViewl.FindltemCFlndltem. lvwSubltem)

Notice that you can’t specify a partial match w’hen searching the subitems, The last two arguments of the Findltem method are ignored when the value argument is IvwSubltenr. If the string isn’t found in the subitems either, then a message is displayed. If the search string is located (either in a Text property or subitem), the matching item is highlighted and it’s brought into view. The code behind the Find Item button is shown next.

The Ensure Visible method scrolls the control’s content so that the selected item comes into the control’s visible area. The Selected property is set to True to highlight the item just located.

Selecting Items

If you experiment a little with the ListViewDemo application you’ll see that the ListView control reacts when items are clicked and/ or double-clicked. A common task in programming the ListView control is have it detect the item that’s clicked or double-clicked upon. The mouse-click on an item is reported to the application with the ItemClick event, whose declaration is as follows:

Private Sub ListViewl_ItemClick(ByVal Item As ComctlLib.ListItem)

The Item argument represents the list item that’s clicked, and you can use it from’ within your code to access the members of the item. However, there is no equivalent ItemDoubleClick event. Yet, many applications must react when the user . double-clicks an item in’ the ListView control.

The left pane is populated from within the Form’s Load event. The code makes use of the FileSystemObject object, which is discussed later in the book. In this section, I will go quickly through the code and explain only the members of the .• FileSystemObject used in this project. Following is the code that populates the TreeView control with the subfolders of the C:\ WINDOWS folder.

. The program sets up the ListView control with four columns and then it creates the Sys variable, which represents the computer’s file system. Through this variable, which is declared on the Form level, other subroutines will be able to access the file system. From within the Load event, only the top-level node, C:\ WINDOWS, is added to the TreeView control. Its child nodes are added by the ScanFolderO
subroutine.

The ScanFolderQ subroutine is a short, recursive procedure that scans all the folders under C:\ WINOOWS and their subfolders. The subroutine’s listing is shown next.

The variable This folder represents the current folder (the one passed to the Scan-Folder() subroutine as argument). Using this variable, the program creates the all- Folders collection, which contains all the subfolders of the current folder. Then, it scans every folder in this collection and adds its name to the Tree’View control. The newly added node’s key is the folder’s path name, so each key will be unique. After adding a folder to the TreeView control, the procedure must scan the subfolders of . the current folder. It does so by calling itself and passing anothe folder’s name as argument. If you find the recursive implementation of the subroutine difficult to understand, go through the material of Chapter 11,Recursive Programming. You can use the ScanFolderO subroutine as is in your projects; just pass to it a reference to the folder you want to scan. The argument to the ScanFolderQ subroutine is a Folder object, not just the name of the folder. The ScanFolderO subroutine must be used.

Viewing a Folder’s Files

To view the files of a folder, click the folder’s name in the Treevitime
the user clicks an item in the TreeView control” the NodeClick,.

This event passes a single argument, which is a reference to the selected node. We use this argument to process the selected node. The processing consists of displaying the selected folder’s files on the ListView control. The listing for TreeView control’s NodeClick handler follows.

After reading the discussion of the FileSystemObject object, you’ ” find this code really easy to understand. The expression FSys.GetFolder(Node. Key returns a reference to the selected {older, which is stored in the variable thisFolder. This variable is then used to retrieve the folder’s files. The statement this FolderFiles returns a collection of nil the files in the selected folder. This collection be accessed through the all Files variable. The following loop scans all the files in the all Files collection:

For Each thisFile In allFiles

Next

At each iteration of the loop, the variable thisFile references a different file and it’s used to access the file’s properties:

thisFile.Name The file’s name
thisFile.Size The file’s size
thisFile.DateCreated The file’s creation date and time
thisFileDateModified The date and-time the file was last modified.

These properties are used to populate the subitems of the current item in the List- View control.

Processing the Selected Files

At the bottom of the ListView control, there is a Label where the number of selected files and their total size is printed. Keeping the label updated at all limes is tricky. Try setting the ListView control’sMultiSelect property to True and inserting the following code in the control’s ItemClick event.

Here’s how the code works: Because the user may select or deselect a file by clicking its name, we can’t Simply add the size of the file that was clicked to the total size. Every time the ltemClick event is triggered, the computer must scan all the ListItems and examine their Selected property. If they’re True, then it incre.ases the number of selected files by one and adds the file’s size to the total size.

This code works in principle, but it has two drawbacks. For one thing, it’s slow quite slow when the ListView control is filled with many filenames. For some reason, the code in the ItemClick event must be as short as possible.

The second, and more annoying, drawback is that it works only when the user selects files with mouse-clicks (while holding down the Shift and Ctrl keys, of course). If you select multiple files on the ListView control with a mouse drag operation Gust press the mouse button, draw a rectangle that encloses ‘a number of files, , . . and then release the mouse button) the label below the ListView control won’t be updated because the ltemClick event won’t be triggered. So, the ItemClick event isn’t where the code belongs.

To figure out where the code should be placed, I tried and discarded the Mouse- Move event (it doesn’t trigger when the user selects multiple files) and the Selection Changed event (the ListView control doesn’t provide a similar event), before using Tuner control to handle all possible selection mechanisms. You can change the Inter
val property of the Tuner control to repeat the operations more or less often, but I the control to repeat the operations every 100 milliseconds. By placing the statements of Code in the Tuner control’s Tuner event, this managed to keep the statistics displayed on the Label control updated at all times, regardless of how the files were selected (with point-and-dick or click-and-drag operations).

Even when I select multiple files with the mouse button and the Shift key, the processing of the files from within the Tuner event is much faster than processing them from within the ItemClick event. Instead of removing the identical code from within the ItemClick event, I’ve commented it out so you can experiment with it. Uncomment the lines in the ItemClick event and run the program to see for yourself how slow the ItemClick event can be, especially with folders that contain man files. Notice that it doesn’t make any difference how many files you select, because the code scans all the files to locate the selected ones.

Scroll to Top