Access ListView SubItem Text by Column Header

Posted on 2006-04-18
Medium Priority
Last Modified: 2010-05-26

I have a ListView that I would like to access SubItem text from the selected row.  The ListView is dynamically populated so I am not always sure what SubItem relates to the info I need.  When populating the listview I included column headers but i am not sure how I can reference a selected listview item subItem by column header.

I can get the value with the following line, however i cant guarantee subitems(5) will be the data i need to get.

val = lvwData.Items(SelectedItemIndex).SubItems(5).Text

If I cant do this direct by column header name, is there some way i can determine the SubItems index by the known column name

Thank you for any advise
Question by:QuinnB74
  • 2
LVL 27

Expert Comment

ID: 16483927
Hi QuinnB74,

I do not know if this will help you ,but here is a sample that you might be able to modify...


Public Class frmClickSubItem
    Inherits System.Windows.Forms.Form

#Region " Windows Form Designer generated code "

    Public Sub New()

        'This call is required by the Windows Form Designer.

        '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
            End If
        End If
    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 Label1 As System.Windows.Forms.Label
    Friend WithEvents ColumnHeader1 As System.Windows.Forms.ColumnHeader
    Friend WithEvents ColumnHeader2 As System.Windows.Forms.ColumnHeader
    Friend WithEvents ColumnHeader3 As System.Windows.Forms.ColumnHeader
    Friend WithEvents ColumnHeader4 As System.Windows.Forms.ColumnHeader
    Friend WithEvents ColumnHeader5 As System.Windows.Forms.ColumnHeader
    Friend WithEvents TextBox1 As System.Windows.Forms.TextBox
    <System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
        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.ColumnHeader4 = New System.Windows.Forms.ColumnHeader
        Me.ColumnHeader5 = New System.Windows.Forms.ColumnHeader
        Me.Label1 = New System.Windows.Forms.Label
        Me.TextBox1 = New System.Windows.Forms.TextBox
        Me.ListView1.Anchor = CType((((System.Windows.Forms.AnchorStyles.Top Or System.Windows.Forms.AnchorStyles.Bottom) _
                    Or System.Windows.Forms.AnchorStyles.Left) _
                    Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles)
        Me.ListView1.Columns.AddRange(New System.Windows.Forms.ColumnHeader() {Me.ColumnHeader1, Me.ColumnHeader2, Me.ColumnHeader3, Me.ColumnHeader4, Me.ColumnHeader5})
        Me.ListView1.FullRowSelect = True
        Me.ListView1.GridLines = True
        Me.ListView1.Location = New System.Drawing.Point(8, 8)
        Me.ListView1.MultiSelect = False
        Me.ListView1.Name = "ListView1"
        Me.ListView1.Size = New System.Drawing.Size(458, 206)
        Me.ListView1.TabIndex = 0
        Me.ListView1.View = System.Windows.Forms.View.Details
        Me.Label1.Anchor = CType(((System.Windows.Forms.AnchorStyles.Bottom Or System.Windows.Forms.AnchorStyles.Left) _
                    Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles)
        Me.Label1.Location = New System.Drawing.Point(8, 222)
        Me.Label1.Name = "Label1"
        Me.Label1.Size = New System.Drawing.Size(190, 16)
        Me.Label1.TabIndex = 1
        Me.Label1.Text = "Label1"
        Me.TextBox1.Location = New System.Drawing.Point(212, 220)
        Me.TextBox1.Name = "TextBox1"
        Me.TextBox1.TabIndex = 2
        Me.TextBox1.Text = "TextBox1"
        Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
        Me.ClientSize = New System.Drawing.Size(478, 244)
        Me.Name = "frmClickSubItem"
        Me.Text = "Form1"

    End Sub

#End Region

    Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As IntPtr, ByVal lMsg As Integer, ByVal wParam As Integer, ByRef lParam As RECT) As Integer

    Private Structure RECT
        Public Left As Integer
        Public Top As Integer
        Public Right As Integer
        Public Bottom As Integer
    End Structure
    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Dim i As Integer
        Dim lvi As ListViewItem
        Dim ch As ColumnHeader

        For i = 0 To 10
            lvi = New ListViewItem("Item" & i)
            lvi.SubItems.Add("Subitems" & i * 1)
            lvi.SubItems.Add("Subitems" & i * 2)
            lvi.SubItems.Add("Subitems" & i * 3)
            lvi.SubItems.Add("Subitems" & i * 4)

        For Each ch In ListView1.Columns
            ch.Width = -2
    End Sub
    Private Sub ListView1_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles ListView1.MouseDown
        Label1.Text = "Column " & (GetListViewSubItem(Me.ListView1, New Point(e.X, e.Y)) + 1)
    End Sub

    Public Function GetListViewSubItem(ByVal listView1 As ListView, ByVal pt As Point) As Integer
        Const LVM_FIRST As Integer = &H1000
        Const LVM_GETSUBITEMRECT As Integer = LVM_FIRST + 56
        Const LVIR_BOUNDS As Integer = 0

        Dim myrect As RECT
        Dim lvitem As ListViewItem = listView1.GetItemAt(pt.X, pt.Y)
        If lvitem Is Nothing AndAlso listView1.SelectedItems.Count > 0 Then
            lvitem = listView1.SelectedItems(0)
        End If
        Dim intLVSubItemIndex As Integer = -1
        Dim LVSubItem As ListViewItem.ListViewSubItem = Nothing

        If Not (lvitem Is Nothing) Then
            Dim intSendMessage As Integer
            Dim i As Integer
            lvitem.UseItemStyleForSubItems = False
            For i = 1 To lvitem.SubItems.Count - 1
                LVSubItem = lvitem.SubItems(i)
                myrect = New RECT
                myrect.Top = i
                myrect.Left = LVIR_BOUNDS
                intSendMessage = SendMessage(listView1.Handle, LVM_GETSUBITEMRECT, lvitem.Index, myrect)
                If pt.X < myrect.Left Then
                    LVSubItem = lvitem.SubItems(0)
                    LVSubItem.ForeColor = Color.Red
                    intLVSubItemIndex = 0
                    TextBox1.Text = LVSubItem.Text
                    Exit For
                ElseIf pt.X >= myrect.Left And pt.X <= myrect.Right Then
                    intLVSubItemIndex = i
                    LVSubItem.ForeColor = Color.Orange
                    TextBox1.Text = LVSubItem.Text
                    Exit For
                    LVSubItem = Nothing
                End If
            Next i
        End If
        If LVSubItem Is Nothing OrElse lvitem Is Nothing Then
            intLVSubItemIndex = -1
        End If
        Return intLVSubItemIndex
    End Function

End Class

Author Comment

ID: 16484639
Thanks for the suggestion however the SubItem I am looking for is actually hidden from view (colWidth = 0) so I dont think your solution will apply to my situation. Sorry, I should have been clearer earlier.

Without getting too into it, I have inherited some code whereby the previous developer had a listview to display a dataTable.  This dev implemented column sorting on the listview, however any selection of the listview for action (ie delete) uses the listview selected index and passes that to the function which does the delete.  the Delete function uses the listview index to lookup the record ID in the backend Datatable and then performs the action.  Works great if the listview is unsorted as the indexes will line up, unfortunately ppl want the sort feature.  

I thought the easiest fix was to query the listview for the ID (btw, this is not always limited to one ID, it references multiple foreign keys that i need to perform action on depending on user input) which is added during population with a column width of 0.

Thank you

LVL 96

Accepted Solution

Bob Learned earned 1000 total points
ID: 16489625
Try something like this:

  Public Function GetListViewSubItem(ByVal view As ListView, ByVal index As Integer, ByVal columnName As String) As ListViewItem.ListViewSubItem

    Dim item As ListViewItem = view.Items(index)

    For columnIndex As Integer = 0 To view.Columns.Count - 1
      Dim column As ColumnHeader = view.Columns(columnIndex)
      If column.Text.ToLower() = columnName.ToLower() Then
        Return item.SubItems(columnIndex)
      End If

    Next columnIndex

    Return Nothing

  End Function


Author Comment

ID: 16495535
Thank You Kindly. It seems so logical now.

Featured Post

Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

If you're writing a .NET application to connect to an Access .mdb database and use pre-existing queries that require parameters, you've come to the right place! Let's say the pre-existing query(qryCust) in Access takes a Date as a parameter and l…
It’s quite interesting for me as I worked with Excel using vb.net for some time. Here are some topics which I know want to share with others whom this might help. First of all if you are working with Excel then you need to Download the Following …
Are you ready to place your question in front of subject-matter experts for more timely responses? With the release of Priority Question, Premium Members, Team Accounts and Qualified Experts can now identify the emergent level of their issue, signal…
Despite its rising prevalence in the business world, "the cloud" is still misunderstood. Some companies still believe common misconceptions about lack of security in cloud solutions and many misuses of cloud storage options still occur every day. …

850 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question