
Introduction
Do you want to find an Item in a ListView control without writing a loop to search through the Items collection? Do you need to get the bounding rectangle of an Item or SubItem (in Details view) in a ListView control? Well then, this article is for you!
Background
VB 6 supports a Find() method to find an Item in a ListView control. However, this method is no longer present in VB.NET. So you could write a code to loop through the Items collection, comparing each Item's text with your search text, e.g.:
For Each itm As ListViewItem In ListView1.Items
If exactMatch Then
If itm.Text = mySearchText Then
End If
Else
mySearchText &= "*"
If itm.Text Like mySearchText Then
End If
End If
Next
where mySearchText is the text you are searching for, and exactMatch is a Boolean you've defined to determine if an exact or partial match is to be made. Also, although the ListView Item supports the GetBounds() method to return a rectangle with the bounds of the ListView Item, e.g.:
myRect = ListView1.Items(0).GetBounds(ItemBoundsPortion.Entire)
Unfortunately, ListView SubItem does not, so:
myRect = ListView1.Items(0).SubItems(1).GetBounds(ItemBoundsPortion.Entire)
produces the following error:
'GetBounds' is not a member of 'System.Windows.Forms.ListViewItem.ListViewSubItem'.
Using the code
To use the LVFindItem class, add a new class to your project and replace the generated code with the contents of LVFind.vb. Then, in the code for your form containing a ListView control, add a code similar to the following.
To search for a string in the ListView Items collection:
Dim fPar As Integer = LVFind.LVFindItem.LVFI_PARTIAL
Dim mySearchString As String = "findme"
...
Sub Find()
FindIt(mySearchString, fPar)
End Sub
...
Private Sub FindIt(ByVal SearchString As String, _
Optional ByVal flag As Integer = LVFind.LVFindItem.LVFI_PARTIAL)
Dim lvf As New LVFind.LVFindItem
lvf.LVFnd(ListView1, SearchString, flag)
ListView1.Focus()
End Sub
To get the bounding rectangle of a ListView Item or SubItem:
Dim itmIdx As Integer = 1 Dim colNum As Integer = 2 Dim myRect As Rectangle ...
Sub GetRect()
myRect = Locate(itmIdx, colNum)
End Sub
...
Private Function Locate(ByVal itm As Integer, ByVal col As Integer) As Rectangle
Dim lvf As New LVFind.LVFindItem
Dim rect As New Rectangle
rect = lvf.GetSubItemRect(ListView1, itm, col, LVFind.LVFindItem.LVIR_LABEL)
Return rect
End Function
Points of Interest
Interestingly, on MSDN, under the definition of the LVM_GETSUBITEMRECT message, the definition of the LVIR_LABEL flag value states that it is identical to LVIR_BOUNDS. This is incorrect, at least when the ListView control is in Details view. Try changing the flag's value in the LVFind test code (hint: I'm already using LVIR_LABEL, so change it to LVIR_BOUNDS and give it a try).
History
23rd Jan 2005 - First release.