Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

WinForms ListView Find & GetSubItemRect

0.00/5 (No votes)
23 Jan 2005 1  
Overcoming some limitations of the WinForms ListView control.

Sample Image - LVFind.gif

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
               ' an exact match was found ...

            End If
         Else
            mySearchText &= "*"
            If itm.Text Like mySearchText Then
               ' a partial match was found ...

            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
   ...
   ' Search for SearchString in ListView1 Items

   Private Sub FindIt(ByVal SearchString As String, _
    Optional ByVal flag As Integer = LVFind.LVFindItem.LVFI_PARTIAL)
      ' Make an instance of the LVFindItem class

      Dim lvf As New LVFind.LVFindItem
      ' Call the LVFnd() sub

      '   1st parm is ListView control

      '   2nd parm is text to find

      '   3rd parm (optional) is flag value (see LVFindItem class for definition)

      lvf.LVFnd(ListView1, SearchString, flag)
      ' Focus the ListView control so we can see which item is selected

      ListView1.Focus()
   End Sub

To get the bounding rectangle of a ListView Item or SubItem:

   Dim itmIdx As Integer = 1 ' The index of the Item in the Items collection

   Dim colNum As Integer = 2 ' The column of the Item or SubItem

   Dim myRect As Rectangle ' Holds the return value from Locate()

   ...
   Sub GetRect()
      myRect = Locate(itmIdx, colNum)
   End Sub
   ...
   'Get bounding rectangle of Item itm, Column col

   Private Function Locate(ByVal itm As Integer, ByVal col As Integer) As Rectangle
      ' Make an instance of the LVFindItem class

      Dim lvf As New LVFind.LVFindItem
      ' A new Rectangle to hold the return value from GetSubItemRect

      Dim rect As New Rectangle
      ' Call the GetSubItemRect() function

      '   1st parm is ListView control

      '   2nd parm is index of Item to find

      '   3rd parm is column of SubItem to find

      '   4th parm (optional) is flag value (see LVFindItem class for definition)

      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.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here