Alex
Alex

Reputation: 4948

Find listview column index using HitTestInfo

I'm looking to find the index of the column when I right click on the listview items using this code:

Private Sub Source_lvArticles_MouseDown(sender As Object, e As System.Windows.Forms.MouseEventArgs) Handles Source_lvArticles.MouseDown
    If e.Button = System.Windows.Forms.MouseButtons.Right Then
        Sources_RightClickedCol = 0

        Dim info As ListViewHitTestInfo = Source_lvArticles.HitTest(e.X, e.Y)
        Sources_RightClickedCol = info.Location
    End If
End Sub

I am able to find the text of the item that I'm right clicking (info.Subitem.Text), I just can't find its column index...

Upvotes: 1

Views: 4261

Answers (4)

Matej G
Matej G

Reputation: 1

You can also use subitem.tag property to store information about the column while populating the listview and then simply retrieve this information later on with the hittest.(e.X, e.Y).SubItem.tag.

Upvotes: 0

There is a much simpler way to get the "column" clicked:

Private Function GetSubItemIndexAt(x As Integer, y As Integer) As Integer
    ' get HitTextinfo for X,Y
    Dim ht As ListViewHitTestInfo = myLV.HitTest(x, y)

    If ht.Item IsNot Nothing Then
        ' use built in method to get the index
        Return ht.Item.SubItems.IndexOf(ht.SubItem)
    End If

    Return -1           ' (semi) universal not found indicator

End Function

Keep in mind that Index 0 will refer to the Item or Label area.

The only caveat is that HitTest only works where there are actual items. If you click on the non-item area such as a blank area below, that XY will result in no item to work with.

Upvotes: 3

Eddy Jawed
Eddy Jawed

Reputation: 457

Unfortunately with the above code provided by Alex, there is a danger that if more than 1 sub item in a row contains the same text value then it will pick the first left most column index. A better way is just to copy the function below, which simply uses the mouse pointer X value and compares it to the columns right values, where X exceeds at which point we have the integer on a loop count:

Private Function GetColumnIndex(ByVal lvw As ListView, ByVal MouseX As _
Integer) As Integer

    Dim result As Integer = 0

    'Get the right and width pixel values of all the columns 
    Dim ColW As New List(Of Integer)
    Dim Index As Integer = 0


    For Each col As ColumnHeader In lvw.Columns
        ColW.Add(col.Width)
        Dim X As Integer = 0
        For i As Integer = 0 To ColW.Count - 1
            X += ColW(i)
        Next

        'Once you have the rightmost values of the columns 
        'just work out where X falls in between

        If MouseX <= X Then
            result = Index
            Exit For
        End If

        Index += 1

    Next

    Return result
End Function

Upvotes: 2

Alex
Alex

Reputation: 4948

For those wondering what I did to figure out my column index ... It's not very elegant, but it works.

Private Sub Source_lvArticles_MouseDown(sender As Object, e As System.Windows.Forms.MouseEventArgs) Handles Source_lvArticles.MouseDown
    If e.Button = System.Windows.Forms.MouseButtons.Right Then
        Sources_RightClickedCol = 0

        Dim info As ListViewHitTestInfo = Source_lvArticles.HitTest(e.X, e.Y)
        Dim SubItem As String = info.SubItem.Text

        For Each item As ListViewItem In Source_lvArticles.Items
            Dim i As Integer = 1
            Dim found As Boolean = False
            For Each s As ListViewItem.ListViewSubItem In item.SubItems
                If s.Text = SubItem Then
                    Sources_RightClickedCol = i
                    found = True
                    Exit For
                End If
                i += 1
            Next
            If found Then Exit For
        Next
    End If
End Sub

What this does is go through each subitem of each row in the listview and keep count of the column index (i). It compares the text of the current subitem to the one that was detected by the HitTest

Upvotes: 0

Related Questions