This is my current method for populating the sub-items of ListView controls. I like this method for two reasons...

1) I don't have to keep up with the display order of the columns.

2) If I enable column re-ordering, I don't have to change anything with the code.

So, the question is... Is this a good approach? Can it be improved?

Note: I'm not too happy about declaring Result As Object. It seems like there should be a better way to handle that, but it's the only way I could get it to working.

Private Function RetrieveItem(Of T)(ByVal displayIndex As Integer) As T
    Dim Result As Object = If(GetType(T) Is GetType(ListViewItem), New ListViewItem, New ListViewItem.ListViewSubItem)
    Select Case displayIndex
        Case ColumnHeader1.DisplayIndex
            Result.Text = "First Item"
            Result.Tag = "First"
        Case (ColumnHeader2.DisplayIndex)
            Result.Text = "Second Column"
            Result.Tag = "Second"
        Case ColumnHeader3.DisplayIndex
            Result.Text = "Third Column"
            Result.Tag = "Third"
        Case ColumnHeader4.DisplayIndex
            Result.Text = "Fourth Column"
            Result.Tag = "Fourth"
    End Select
    Return Result
End Function

Example Usage...

Dim item As ListViewItem = RetrieveItem(Of ListViewItem)(0)
For i As Integer = 1 To ListView1.Columns.Count - 1
    item.SubItems.Add(RetrieveItem(Of ListViewItem.ListViewSubItem)(i))

Here is the example I came up with using @MarkHurd's suggestion of using a Widening CType Operator...

Private Class LVI
    Public Name As String
    Public Text As String
    Public Tag As Object
    Public Sub New(ByVal name As String, ByVal text As String, ByVal tag As Object)
        Me.Name = name
        Me.Text = text
        Me.Tag = tag
    End Sub
    Public Shared Widening Operator CType(ByVal item As LVI) As ListViewItem
        Dim Result As New ListViewItem(item.Text)
        Result.Name = item.Name
        Result.Tag = item.Tag
        Return Result
    End Operator
    Public Shared Widening Operator CType(ByVal item As LVI) As ListViewItem.ListViewSubItem
        Dim Result As New ListViewItem.ListViewSubItem
        Result.Text = item.Text
        Result.Name = item.Name
        Result.Tag = item.Tag
        Return Result
    End Operator
End Class

Private Function RetrieveItem(ByVal index As Integer) As LVI
    Select Case index
        Case ColumnHeader1.DisplayIndex : Return New LVI("1", "First Column", "one")
        Case ColumnHeader2.DisplayIndex : Return New LVI("2", "Second Column", "two")
        Case ColumnHeader3.DisplayIndex : Return New LVI("3", "Third Column", "three")
        Case ColumnHeader4.DisplayIndex : Return New LVI("4", "Fourth Column", "four")
        Case Else : Return Nothing
    End Select
End Function

Example usage...

Dim item As ListViewItem = RetrieveItem(0)
For i As Integer = 1 To ListView1.Columns.Count - 1

I like both of these approaches, but I feel like the first is shorter and easier to implement, so I lean towards the first option.

  • \$\begingroup\$ What's wrong with your expected problem of editing the font color? How is this not possible with your code (with obvious changes to actually try something, since your code does not seem to do anything with font color ATM)? \$\endgroup\$ – Gaffi Jul 24 '12 at 13:49
  • \$\begingroup\$ @Gaffi, In the original code you would have had to return a custom structure, or class, which I think would be tedious, or make a new function for each property. I have changed the code to use Generic Types instead which should overcome that problem. \$\endgroup\$ – Drew Chapin Jul 24 '12 at 15:09
  • \$\begingroup\$ "I'm not too happy about declaring Result As Object." That's not your fault: Microsoft should have at least defined an interface that both ListViewItem and ListViewSubItem implemented. \$\endgroup\$ – Mark Hurd Jul 25 '12 at 16:18

If you want to avoid the late bound .Text and .Tag you could just create your own private type, say LVI, containing these two properties and implicit Widening CType operators for ListViewItem and ListViewItem.ListViewSubItem. Then the Result As New LVI can be converted on return using Return CType(CTypeDynamic(Result, GetType(T)), T) in the latest VB.NET.

Without CTypeDynamic I don't have a working solution yet.

| improve this answer | |
  • 1
    \$\begingroup\$ I was previously unaware of Widening CType. Your suggestion looks promising... I think when I get a chance, I will experiment with that approach and see how it turns out. If I like it, I'll post it as an addendum to my question. \$\endgroup\$ – Drew Chapin Jul 25 '12 at 22:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.