What is the proper way to change what ListBox.Items holds?

In an effort to get rid of VB6.Get/SetItemData from a VB6 project upgraded to .NET, the project has been changed to use custom object classes (e.g., with Name and Data members) in collections. This works fine, but has the performance-overhead and type-unsafety arising from the ListBox.Items member being a generic ObjectCollection.

What would be better is to create a subclass of a Listbox that is exactly the same as a normal one, except with a type-safe collection for the Items member instead of a generic object collection; that is Items should be a System.Collections.Generic.List(Of SomeType) rather than just an ObjectCollection.

I have spent several hours trawling through MDSN, VB Help and the internet, but everybody seems to suggest different methods, such as abusing "shadowing" (because Items is not overridable), overriding the CreateItemCollection() method, or using a DataSource (not applicable, because apparently, it makes Add() and Remove() methods stop working).

Being new to .NET, I would like to know what the "proper" way to do this is. Would somebody please tell me


Answer this question

What is the proper way to change what ListBox.Items holds?

  • Aaron Steers

    Hey martin, you might be interested in Expert VB 2005 Business Objects

    check this search



  • jswilson

    OK; here as promised is the generic SortedBindingList(Of T) together with a simple test-harness and demonstration program. This is what was needed and hopefully, it will help others in my position. Download it at: http://www.martinsobservationpost.net/files.htm#SortedBindingList

    Thanks to all who assisted and all those out there who post code examples to help each other out.

    Martin Howe
    23rd June 2006


  • Hayder Marzouk

    After conducting some experiments and looking in other places, it seems there is a workaround that can suffice in simple cases. Basically, object collections, along with several other data types, don't implement the necessary interfaces for auto-updating a control that is bound to them; however, if binding is turned off, then back on after each change to the data, it causes the control to refresh its list.

    DataList.Add(something)
    ListBox1.DataSource = Nothing
    ListBox1.DataSource = Things


    DataList.RemoveAt(somenumber)
    ListBox1.DataSource = Nothing
    ListBox1.DataSource = Things

    This is not optimal and there is a way to suspend then restore binding, but the documentation for that is highly detailed and will take a while to understand since it doesn't give an overall worked example for non-database data; however, this ought to be good enough for a small list of items that is modified infrequently.

    To save others the work I had to do to find this out, a small working example program can be downloaded here if anyone wants it: http://www.martinsobservationpost.net/public/BindingExperiments.zip It is nothing fancy, just a small form to demonstrate the principle.

  • Fab IT

    Thanks, that works!

    Just so anybody else considering doing this is aware of it, there are two problems that have to be overcome. One is that when an empty ListBox updates itself to add a [first] item in response to the List adding a first item, the ListBox selects the item. The other is that when the last item in the List is removed and the ListBox updates itself accordingly, the ListBox makes the next item down become selected, even if it was not selected before.

    To deal with the first problem, use something like this:

    Things.Add(New Thing(EnterThingName.Text, CInt(EnterThingData.Text)))
    ThingsListing.SetSelected(Things.Count - 1, False)

    To deal with the second use something like this:

    Dim ItemIndex As Integer = ThingsListing.SelectedIndex
    Dim WasSelected As Boolean = False
    If ItemIndex > 0 AndAlso ThingsListing.GetSelected(ItemIndex - 1) Then
    WasSelected = True
    End If
    Things.RemoveAt(ItemIndex)
    If ItemIndex > 0 And Not WasSelected Then
    ThingsListing.SetSelected(ItemIndex - 1, False)
    End If


    Finally, the list itself is not sorted, the way a ListBox is. I found an example on GotDotNet of how to make a sorted list of a specific type and have, after much trial and error, created from that a sorted generic Binding List class. I'll clean it up and post a link to it tomorrow, in case it helps out somebody else in the same position, then mark this question as answered.

  • reZer

    set datasource to your generic collection, perform operations on the collection, not list box.items.

    dim myItems as new ListBox(Of MyClass) ' Be sure to override ToString in MyClass

    ListBox1.DataSource = myItems

    then you can do this:

    myItems.Remove(ListBox1.SelectedItem)

    The controls is just a presentation for your data structure. don't use it as your data structure.

    Here's a good place to start: Data Binding and Windows Forms

    Also dig into this: Providers of Data to Windows Forms

    but the key is - Manipulate the structure the control is bound to, do not, i repeat do not use your control as a data structure. That was wrong in VB6 as well (albeit databinding in VB6 wasn't that friendly. . . still waiting for someone to explain how VB6 became so popular. Man, what a dog!)



  • sp_412000

    sorry. . . bad typing. . . Ive been doing alot of that lately!!!

    should have said BindingList (of MyClass)



  • yennisse

    I've never come across the concept of datasources and databindings outside of databases, but can see the point of it. So the "new way of thinking", it seems, is that the "database" way of doing things is considered best, even for simple in-memory objects, not just for thousands of records in a huge file. Interesting; thanks, I'll check it out.

    As it happens, the list in question wasn't bound to anything and while that particular list really was used to manipulate data that it visually represented, the original author of this code often used various list-oriented controls, hidden off the edge of the form where they couldn't be seen, purely for their data structures (shudder).

    EDIT: Looks like I spoke too soon. The line dim myItems as new ListBox(Of MyClass) in the above example says that dimming a ListBox with a type is illegal. Using this:

    Private ImportList As New System.Collections.Generic.List(Of FlaggedListItem)
    List1.DataSource = ImportList

    seems to work at first, but the ListBox List1 does not update when ImportList is modified; in fact, after adding two items to ImportList (and confirming in the debugger), List1 is empty! I did look at the references given, but they are all very database-orientated and are very heavy going for a newcomer to databinding. Can anyone give a link to a working example of a ListBox control being used to mirror an array or collection; something I can pick apart and learn from that is relevant to simple collections, not databases Surely somebody must have done this before

  • What is the proper way to change what ListBox.Items holds?