Finding Items in ListView

  • Thread starter Thread starter Mike Smith
  • Start date Start date
M

Mike Smith

Hey anyone knows how to find an item in a list view based on text ? Cant
seem to get the IndexOf method working.
would the LVM_FINDITEM method using SendMessage API work in .Net ?
 
Hi Mike,

I did not try it or ever used it, but did you try this
\\\
dim i as integer = DirectCast(ListView1, IList).IndexOf("")
///

Cor
 
Cor,

* "Cor said:
I did not try it or ever used it, but did you try this
\\\
dim i as integer = DirectCast(ListView1, IList).IndexOf("")
///

This won't work because 'ListView' doesn't implement the 'IList'
interface, but you may want to try to cast 'ListView.Items' (which is an
'ListView.ListViewItemCollection' and implements the 'IList' interface).
 
I did not check it, because I knew Ilist was implementing Listview but did
not check how.

After checking it I think you are right.

So that will be
I am answering to fast now

Cor
 
* "Cor said:
I did not check it, because I knew Ilist was implementing Listview but did
not check how.

After checking it I think you are right.

So that will be

I am answering to fast now

I hope it will work.
 
Hi Mike,

I assume that you get with this method only if something exist in the items
and not in the sub items, I think that there will be a possibility to use
this also on the sub items, because that is also derived from Ilist, but I
did not see it in the documentation.

Why not just do a for each loop.
The listview is a complex control you know and using it simple will helps
mostly.

Cor
 
yeah resorted to looping it but not the real best solution rite ?

used to be a sendmessage() API call that would work.. i tried using it in
..net but it didnt seem to work ....

the ListView.Items.IndexOf(listitem) does manage to find the listitem object
but thats if we are using a unique listitem each time we add an item into
the list. Who would do such a thing? Of course we're gonna reuse the same
variable in a loop to add items into the listview. There should be some
faster way to find an item/subitem in a listview more efficiently ?
 
Hi Mike,

Why a listview, a listview is for me a control that the user uses to click
on.

I would think on a datagrid with an underlaying table that I could search.

Cor
 
Mike said:
yeah resorted to looping it but not the real best solution rite ?

used to be a sendmessage() API call that would work.. i tried using it in
.net but it didnt seem to work ....

the ListView.Items.IndexOf(listitem) does manage to find the listitem object
but thats if we are using a unique listitem each time we add an item into
the list. Who would do such a thing? Of course we're gonna reuse the same
variable in a loop to add items into the listview. There should be some
faster way to find an item/subitem in a listview more efficiently ?

Mike...

Here is an example of using the LVM_FINDITEM and SendMessage...

Option Strict On
Option Explicit Off

Imports System.Diagnostics
Imports System.Runtime.InteropServices

Public Class Form1
Inherits System.Windows.Forms.Form

#Region " Windows Form Designer generated code "

Public Sub New()
MyBase.New()

'This call is required by the Windows Form Designer.
InitializeComponent()

'Add any initialization after the InitializeComponent() call

End Sub

'Form overrides dispose to clean up the component list.
Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
If disposing Then
If Not (components Is Nothing) Then
components.Dispose()
End If
End If
MyBase.Dispose(disposing)
End Sub

'Required by the Windows Form Designer
Private components As System.ComponentModel.IContainer

'NOTE: The following procedure is required by the Windows Form Designer
'It can be modified using the Windows Form Designer.
'Do not modify it using the code editor.
Friend WithEvents ListView1 As System.Windows.Forms.ListView
Friend WithEvents ColumnHeader1 As System.Windows.Forms.ColumnHeader
Friend WithEvents ColumnHeader2 As System.Windows.Forms.ColumnHeader
Friend WithEvents ColumnHeader3 As System.Windows.Forms.ColumnHeader
<System.Diagnostics.DebuggerStepThrough()> Private Sub
InitializeComponent()
Dim ListViewItem1 As System.Windows.Forms.ListViewItem = New
System.Windows.Forms.ListViewItem(New String() {"First", "Sub1",
"Sub2"}, -1)
Dim ListViewItem2 As System.Windows.Forms.ListViewItem = New
System.Windows.Forms.ListViewItem(New String() {"Fourth", "Sub1",
"Sub2"}, -1)
Dim ListViewItem3 As System.Windows.Forms.ListViewItem = New
System.Windows.Forms.ListViewItem(New String() {"Second", "Sub1",
"Sub2"}, -1)
Dim ListViewItem4 As System.Windows.Forms.ListViewItem = New
System.Windows.Forms.ListViewItem(New String() {"Thrid", "Sub1",
"Sub2"}, -1)
Me.ListView1 = New System.Windows.Forms.ListView
Me.ColumnHeader1 = New System.Windows.Forms.ColumnHeader
Me.ColumnHeader2 = New System.Windows.Forms.ColumnHeader
Me.ColumnHeader3 = New System.Windows.Forms.ColumnHeader
Me.SuspendLayout()
'
'ListView1
'
Me.ListView1.Columns.AddRange(New
System.Windows.Forms.ColumnHeader() {Me.ColumnHeader1, Me.ColumnHeader2,
Me.ColumnHeader3})
Me.ListView1.Dock = System.Windows.Forms.DockStyle.Fill
Me.ListView1.Items.AddRange(New
System.Windows.Forms.ListViewItem() {ListViewItem1, ListViewItem2,
ListViewItem3, ListViewItem4})
Me.ListView1.Location = New System.Drawing.Point(0, 0)
Me.ListView1.Name = "ListView1"
Me.ListView1.Size = New System.Drawing.Size(292, 273)
Me.ListView1.TabIndex = 0
Me.ListView1.View = System.Windows.Forms.View.Details
'
'Form1
'
Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
Me.ClientSize = New System.Drawing.Size(292, 273)
Me.Controls.Add(Me.ListView1)
Me.Name = "Form1"
Me.Text = "Form1"
Me.ResumeLayout(False)

End Sub

#End Region

Private Const LVM_FIRST As Integer = &H1000
Private Const LVM_FINDITEMA As Integer = LVM_FIRST + 13
Private Const LVM_FINDITEMW As Integer = LVM_FIRST + 83

<Flags()> _
Private Enum LVFI_FLAGS
Param = &H1
Partial = &H8
[String] = &H2
Wrap = &H20
NearestXY = &H40
End Enum

Private Enum VK
Left = &H25
Right = &H27
Up = &H26
Down = &H28
Home = &H24
[End] = &H23
Prior = &H21
[Next] = &H22
End Enum

<StructLayout(LayoutKind.Sequential)> _
Private Structure POINT
Public x As Integer
Public y As Integer
End Structure

<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Auto)> _
Private Structure LVFINDINFO
Public flags As LVFI_FLAGS
Public psz As String
Public lParam As IntPtr
Public pt As POINT
Public vkDirection As VK
End Structure

Private Declare Auto Function SendMessage Lib "user32" _
(ByVal hWnd As IntPtr, _
ByVal Msg As Integer, _
ByVal wParam As Integer, _
ByRef lParam As LVFINDINFO) As Integer

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load
Dim msg As Integer = CInt(IIf(Marshal.SystemDefaultCharSize >
1, LVM_FINDITEMW, LVM_FINDITEMA))
Dim lvfi As LVFINDINFO

With lvfi
.flags = LVFI_FLAGS.String
.psz = "Second"
End With

MessageBox.Show(SendMessage(ListView1.Handle, msg, -1,
lvfi).ToString())
End Sub
End Class

HTH
 
Hi Mike,

Not that I directy know, but with the datagrid you are always using the
datasource.

Mostly a datatable. And to search in that underlaying table has very much
posibilities to search in and searching in that way is also a faster.

Cor
Does the datagrid have a search feature that returns the row number itself
?
 
hey man ... thanx .. this is what i wanted... just a quick question on
this..
it only works on items and not subitems ?

Tom Shelton said:
Mike said:
yeah resorted to looping it but not the real best solution rite ?

used to be a sendmessage() API call that would work.. i tried using it in
.net but it didnt seem to work ....

the ListView.Items.IndexOf(listitem) does manage to find the listitem object
but thats if we are using a unique listitem each time we add an item into
the list. Who would do such a thing? Of course we're gonna reuse the same
variable in a loop to add items into the listview. There should be some
faster way to find an item/subitem in a listview more efficiently ?

Mike...

Here is an example of using the LVM_FINDITEM and SendMessage...

Option Strict On
Option Explicit Off

Imports System.Diagnostics
Imports System.Runtime.InteropServices

Public Class Form1
Inherits System.Windows.Forms.Form

#Region " Windows Form Designer generated code "

Public Sub New()
MyBase.New()

'This call is required by the Windows Form Designer.
InitializeComponent()

'Add any initialization after the InitializeComponent() call

End Sub

'Form overrides dispose to clean up the component list.
Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
If disposing Then
If Not (components Is Nothing) Then
components.Dispose()
End If
End If
MyBase.Dispose(disposing)
End Sub

'Required by the Windows Form Designer
Private components As System.ComponentModel.IContainer

'NOTE: The following procedure is required by the Windows Form Designer
'It can be modified using the Windows Form Designer.
'Do not modify it using the code editor.
Friend WithEvents ListView1 As System.Windows.Forms.ListView
Friend WithEvents ColumnHeader1 As System.Windows.Forms.ColumnHeader
Friend WithEvents ColumnHeader2 As System.Windows.Forms.ColumnHeader
Friend WithEvents ColumnHeader3 As System.Windows.Forms.ColumnHeader
<System.Diagnostics.DebuggerStepThrough()> Private Sub
InitializeComponent()
Dim ListViewItem1 As System.Windows.Forms.ListViewItem = New
System.Windows.Forms.ListViewItem(New String() {"First", "Sub1",
"Sub2"}, -1)
Dim ListViewItem2 As System.Windows.Forms.ListViewItem = New
System.Windows.Forms.ListViewItem(New String() {"Fourth", "Sub1",
"Sub2"}, -1)
Dim ListViewItem3 As System.Windows.Forms.ListViewItem = New
System.Windows.Forms.ListViewItem(New String() {"Second", "Sub1",
"Sub2"}, -1)
Dim ListViewItem4 As System.Windows.Forms.ListViewItem = New
System.Windows.Forms.ListViewItem(New String() {"Thrid", "Sub1",
"Sub2"}, -1)
Me.ListView1 = New System.Windows.Forms.ListView
Me.ColumnHeader1 = New System.Windows.Forms.ColumnHeader
Me.ColumnHeader2 = New System.Windows.Forms.ColumnHeader
Me.ColumnHeader3 = New System.Windows.Forms.ColumnHeader
Me.SuspendLayout()
'
'ListView1
'
Me.ListView1.Columns.AddRange(New
System.Windows.Forms.ColumnHeader() {Me.ColumnHeader1, Me.ColumnHeader2,
Me.ColumnHeader3})
Me.ListView1.Dock = System.Windows.Forms.DockStyle.Fill
Me.ListView1.Items.AddRange(New
System.Windows.Forms.ListViewItem() {ListViewItem1, ListViewItem2,
ListViewItem3, ListViewItem4})
Me.ListView1.Location = New System.Drawing.Point(0, 0)
Me.ListView1.Name = "ListView1"
Me.ListView1.Size = New System.Drawing.Size(292, 273)
Me.ListView1.TabIndex = 0
Me.ListView1.View = System.Windows.Forms.View.Details
'
'Form1
'
Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
Me.ClientSize = New System.Drawing.Size(292, 273)
Me.Controls.Add(Me.ListView1)
Me.Name = "Form1"
Me.Text = "Form1"
Me.ResumeLayout(False)

End Sub

#End Region

Private Const LVM_FIRST As Integer = &H1000
Private Const LVM_FINDITEMA As Integer = LVM_FIRST + 13
Private Const LVM_FINDITEMW As Integer = LVM_FIRST + 83

<Flags()> _
Private Enum LVFI_FLAGS
Param = &H1
Partial = &H8
[String] = &H2
Wrap = &H20
NearestXY = &H40
End Enum

Private Enum VK
Left = &H25
Right = &H27
Up = &H26
Down = &H28
Home = &H24
[End] = &H23
Prior = &H21
[Next] = &H22
End Enum

<StructLayout(LayoutKind.Sequential)> _
Private Structure POINT
Public x As Integer
Public y As Integer
End Structure

<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Auto)> _
Private Structure LVFINDINFO
Public flags As LVFI_FLAGS
Public psz As String
Public lParam As IntPtr
Public pt As POINT
Public vkDirection As VK
End Structure

Private Declare Auto Function SendMessage Lib "user32" _
(ByVal hWnd As IntPtr, _
ByVal Msg As Integer, _
ByVal wParam As Integer, _
ByRef lParam As LVFINDINFO) As Integer

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load
Dim msg As Integer = CInt(IIf(Marshal.SystemDefaultCharSize >
1, LVM_FINDITEMW, LVM_FINDITEMA))
Dim lvfi As LVFINDINFO

With lvfi
.flags = LVFI_FLAGS.String
.psz = "Second"
End With

MessageBox.Show(SendMessage(ListView1.Handle, msg, -1,
lvfi).ToString())
End Sub
End Class

HTH
 
Back
Top