Adjusting to life without ItemData

In VB6, the ListBox and ComboBox controls had the ItemData property. This was a “companion” list of long integers which could be used to store additional information related to an Item. For example, you could display a list of individuals in a ListBox and keep their age in the ItemData property:

    Dim Pos As Integer
    
    Pos = List1.AddItem("Sneezy")
    List1.ItemData(Pos) = 44
    Pos = List1.AddItem("Grumpy")
    List1.ItemData(Pos) = 56
    Pos = List1.AddItem("Dopey")
    List1.ItemData(Pos) = 22

The .NET ListBox class no longer contains an ItemData property. However, it is no longer necessary since the ListBox class in .NET gives us a more power and control for maintaining the items.

All .NET objects are derived from System.Object. This gives every .NET object a base set of methods:

 Equals
 GetHashCode
 GetType
 ToString

It’s the last one, ToString, which will help us with the ListBox. By default, the ToString method returns the fully qualified name of the type of the Object. However, most classes override this property to provide something meaningful. For example, you might have an Employee class where the ToString method is overridden to return the Employee’s full name:

Public Class Employee
    
Private m_FirstName As String
    Private m_LastName As String

    Public Sub New(firstName As String, lastName As String)
        m_FirstName = firstName
        m_LastName = lastName
    
End Sub

    Public Overrides Function ToString() As String
        Return m_LastName & ", " & m_FirstName
    
End Function
End
 Class

The designers of .NET’s ListBox class decided to use this to their advantage. When adding items to a ListBox, you're no longer restricted to only String values. In fact, the ListBox.Items.Add() method accepts an “Object” datatype. Therefore, you can add anything you want to a .NET ListBox -- a String, an Integer, an Employee object -- anything!

Here’s an example of populating a ListBox with three Employee objects:

ListBox1.Items.Add(New Employee("Jon""Smith"))
ListBox1.Items.Add(
New Employee("Mike""Smith"))
ListBox1.Items.Add(
New Employee("Dolly""Madison"))

You might be asking, “So what gets displayed in the ListBox if I add an Employee object”? The .NET ListBox will use the objects “ToString” method to determine the value that will be displayed in the ListBox. It still holds a reference to the entire Employee object, but the return value of the ToString method is used to display a value in the ListBox.

Next question: What if you’re already overriding ToString() to provide different functionality and its output would not be useful for the ListBox? No problem -- the .NET designers thought of that. The “DisplayMember” property can be used to tell .NET which property to use to obtain the value to be displayed. For example, let’s change our Employee class to provide a FullName property:

Public Class Employee
    
Private m_FirstName As String
    Private m_LastName As String

    Public Sub New(firstName As String, lastName As String)
        m_FirstName = firstName
        m_LastName = lastName
    
End Sub

    Public ReadOnly Property FullName As String
        Get
            Return m_LastName & ", " & m_FirstName
        
End Get
    End Property
End
 Class

You can use the same code shown earlier to populate the ListBox, but now, set the DisplayMember property before adding the items:

ListBox1.DisplayMember = "FullName"

As you can see, .NET make maintaing the items in a ListBox easier and more powerful.

7 Comments

  • This is an excellent tip. One thing I noticed is that if your propery is defined using the lazy way like



    public FullName As String



    and set as the display member using



    ListBox1.DisplayMember = "FullName"

    , it won't work as expected.

  • Yuqin,



    That's because they way you describe is not only "lazy", it's not defining a property -- it's defining a field. The framework uses reflection to find the *property* indicated by DisplayMember. If you define it as a field, it won't work.

  • Wow, even I knew that much before I condescendingly criticized. I guess he never studied C or C+ before C++ and this new fangled C# stuff. Gee, look at that. It's all just still C to me, call me Father Dos. These darn kids today.

  • Here's an easier approach to getting a concatenated displaymember in the dataset: add a new column to the dataset, run a for loop and add a string to the new field in each row. Then set the displaymembew the newly populated column.

  • Thanks for posting this info. I searched for almost an hour and didn't find anything worth while until I came across your article. Thanks for creating a clear and usefull example.



    Chris Walker

    chris@techsolutionslab.com

  • Same here. I wasnt sure how to implement this until i came across this post.

  • Thanks Patrick for sharing this information. I was pulling my hair out trying to find a workable solution without too many memory overheads.

    This is spot-on mate!

Comments have been disabled for this content.