MGBrown.com

A VB.Net equivalent of ComboBox.ItemData

A friend of mine asked me how would you do this in .net?

combobox1.add("first item")
combobox1.itemdata(combobox1.newindex) = 1
combobox1.add("second item")
combobox1.itemdata(combobox1.newindex) = 2
combobox1.add("third item")
combobox1.itemdata(combobox1.newindex) = 3

The solution we came up with is as follows. First you create a new class to hold the data you require:

Public Class ValueDescriptionPair
 
    Public Value As Object
    Public Description As String
 
    Public Sub New(ByVal NewValue As Object, ByVal NewDescription As String)
         Value = NewValue
        Description = NewDescription
    End Sub
 
    Public Overrides Function ToString() As String
        Return Description
    End Function
 
End Class

To add items to the list you use code like this:

Private Sub Form1_Load _
(ByVal sender As System.Object, ByVal e As System.EventArgs) _
Handles MyBase.Load
 
    ComboBox1.Items.Add(New ValueDescriptionPair(1, "first item"))
    ComboBox1.Items.Add(New ValueDescriptionPair(2, "second item"))
    ComboBox1.Items.Add(New ValueDescriptionPair(3, "third item"))
 
End Sub

The next code snippet get the value stored in Value and displays in a message box:

Private Sub ComboBox1_SelectedValueChanged _
(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles ComboBox1.SelectedValueChanged
 
    Dim ItemSelected As Integer
    ItemSelected = CType(ComboBox1.SelectedItem, _
        ValueDescriptionPair).Value
    MsgBox("Value Selected = " & ItemSelected, MsgBoxStyle.Information)
 
End Sub

Despite the fact that it's more work than the VB6 approach, it is actually a very powerful way of doing things. There is no limit to the number of Values or Functions you could add to your ValueDescriptionPair class.

Comments

Re: A VB.Net equivalent of ComboBox.ItemData

The solution above is great however try this:

Instead of adding your data class directly to the combobox add it to an ArrayList

Dim VDP_Array As New ArrayList
VDP_Array.Add(New ValueDescriptionPair(1, "first item"))
VDP_Array.Add(New ValueDescriptionPair(2, "second item"))
VDP_Array.Add(New ValueDescriptionPair(3, "third item"))

Then you can set the ArrayList to the DataSource property of the ComboBox. This then allows you to control better which properties of your data class you want to be the DisplayMember and the ValueMember.

With ComboBox1
.DisplayMember = "Description"
.ValueMember = "Value"
.DataSource = VDP_Array
End With

When you then query ComboBox1.SelectedValue this will return just the Value, without having to convert it back in to the data class.

Also the data class seams to work better if I defined the Value and Description as read-only properties.

e.g.

Public Class ValueDescriptionPair

Private m_Value As Object
Private m_Description As String

Public ReadOnly Property Value() As Object
Get
Return m_Value
End Get
End Property

Public ReadOnly Property Description() As String
Get
Return m_Description
End Get
End Property

Public Sub New(ByVal NewValue As Object, ByVal NewDescription As String)
m_Value = NewValue
m_Description = NewDescription
End Sub

Public Overrides Function ToString() As String
Return m_Description
End Function

End Class

Si

Comment from Simon Phillips at Friday, 26 March 2004 12:51PM (GMT+00)

Re: A VB.Net equivalent of ComboBox.ItemData

Oh BTW, if you then require to get back to the data class, say if you binded a more complecated class to the combobox then use -ComboBox1.SelectedItem property instead.

This works with most of the .Net control e.g. ListBoxes

Comment from Simon Phillips at Friday, 26 March 2004 12:56PM (GMT+00)

Re: A VB.Net equivalent of ComboBox.ItemData

If you have filled the combo box with strings then the following will work:

ComboBox1.Items.Add
ComboBox1.Items.Add("second item")
ComboBox1.SelectedItem = "first item"

If you have filled the combo box solely with ValueDescriptionPairs as in my example then it requires a little more work:

For Each vdp As ValueDescriptionPair In ComboBox1.Items
If vdp.Description = TextBox1.Text Then
ComboBox1.SelectedItem = vdp
Exit For
End If
Next

This will fail though if you have used any objects that are not of type ValueDescriptionPair. In this instance you need to use the following:

For Each o As Object In ComboBox1.Items
If o.ToString() = TextBox1.Text Then
ComboBox1.SelectedItem = o
Exit For
End If
Next

Comment from Martin G. Brown at Wednesday, 18 August 2004 11:06PM (GMT+00)

Re: A VB.Net equivalent of ComboBox.ItemData

Thank you for posting this. I have an app with many combo boxes and was very annoyed to see that .net didn't have the functionality that the control had on vb6.

Comment from Kevin at Thursday, 04 August 2005 04:18PM (GMT+00)

Re: A VB.Net equivalent of ComboBox.ItemData

For some reason the whole method does not work for me. I get the error

"Overload resolution failed because no accessible 'Add' can be called with these arguments".

What the hell am i missing ?

Daniel

Comment from Dan at Thursday, 06 October 2005 12:19PM (GMT+00)

Re: A VB.Net equivalent of ComboBox.ItemData

Without seeing the exact code, it is difficult to say exactly what is causing your error.

The ComboBox.Items.Add method takes just one object as a parameter, there are no other overloads that take more or less parameters. It may be that you passing more than one or no parameters. You should also check that what you are passing is an object and not a Class type, this is the reason for the 'new' keyword in my example.

Comment from Martin G. Brown at Thursday, 06 October 2005 04:12PM (GMT+00)

Re: A VB.Net equivalent of ComboBox.ItemData

Hi,

But nobody ever tried to say what to do when it comes to using a dataset that is the resultant of a database query. Would be great if somebody can answer that.

Thanks in advance

Comment from Rajiv at Thursday, 29 December 2005 09:35AM (GMT+00)

Re: A VB.Net equivalent of ComboBox.ItemData

Rajiv,

Try looking at this post http://www.mgbrown.com/PermaLink40.aspx

It demonstrates using a prepopulated dataset. All you have to do is replace the DataSet creation code with your database query.

Comment from Martin G. Brown at Tuesday, 03 January 2006 10:43AM (GMT+00)

Re: A VB.Net equivalent of ComboBox.ItemData

Hi,

I was wondering if you had any suggestions for populating a ComboBox with items from table in your database and using the primary key field as the ItemData?

Thanks,
Linda

Comment from Linda at Thursday, 19 January 2006 06:57PM (GMT+00)

Re: A VB.Net equivalent of ComboBox.ItemData - selection

Many thanks for this great example, which is working fine in terms of filling my three combo boxes (Author, Client, and Category) from database tables. I am puzzled about the subsequent behaviour of the combo boxes though.

On running the form, the three combos each display the first item from their respective tables, but when I make a different selection in any of the combos, say Author, all of the combos are cleared of any displayed data. If I once more select the Author I want, the selection is retained, and the remaining combos then behave as I think they should as well.

I'm new to VB.Net, and I suppose this is some fundamental that I've missed so far, but I'd be grateful for any help on how to avoid repeating the selection.

Thanks

Dave

Comment from Dave Macmurchie at Tuesday, 16 May 2006 07:38PM (GMT+00)

Re: A VB.Net equivalent of ComboBox.ItemData - Selection - partial resolution

I should have clarified that I was using Simon's ArrayList modification of Martin's original method. I have now found that when I use Martin's original approach, i.e. adding the VDP objects directly to the combo's Items collection, the problem I described above goes away.

That's nice, but I'm still puzzled about what's up with the ArrayList approach. ArrayLists look like they might be handy items, but is there baggage associated with using them?

Comment from Dave Macmurchie at Tuesday, 16 May 2006 08:52PM (GMT+00)

Re: A VB.Net equivalent of ComboBox.ItemData

well done I allmost used this but I also found:

Me.ComboBox1.DisplayMember = "Name" 'Display the friendly names in the control.
Me.ComboBox1.ValueMember = "Url" 'Expose the full address via the SelectedValue.
Me.ComboBox1.DataSource = favourites
End Sub

Private Sub ComboBox1_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ComboBox1.SelectedIndexChanged
'Get the full address that corresponds to the selected name.
MessageBox.Show(String.Format("The address for '{0}' is '{1}'.", _
Me.ComboBox1.GetItemText(Me.ComboBox1.SelectedItem), _
Me.ComboBox1.SelectedValue))
End Sub
Source:
http://www.vbdotnetforums.com/showthread.php?t=14123

Comment from ton at Thursday, 26 October 2006 12:28PM (GMT+00)

Re: A VB.Net equivalent of ComboBox.ItemData

Ton,

The code you have given solves a slightly different issue that I touched appon in this article: http://www.mgbrown.com/Permalink40.aspx

What is given above was only intended for scenarios where a DataSource is not available.

Comment from Martin G. Brown at Thursday, 26 October 2006 01:51PM (GMT+00)

Re: A VB.Net equivalent of ComboBox.ItemData

Guys,

There is a little problem with this code. Let me try explain what happen here.

I added the class above in my project and loaded the combobox1 with States (table STATES).

for example:
ComboBox1.Items.Add(New ValueDescriptionPair(1, "California"))
ComboBox1.Items.Add(New ValueDescriptionPair(2, "Texas"))
...
Ps. in fact I do this: ComboBox1.Items.Add(New ValueDescriptionPair(Drr.Item("IdState").ToString, Drr.Item("State").ToString()))

There is another table named USER with these fields:
IdUser = 1
NameUser = "JOHN"
StateUser = 1 (FK to table STATE.IdState)


When I try show the fields of this table to edit (for example)
ComboBox1.Text = "California"

these portion of code is run a lot of times.. once for each state.

Public Overrides Function ToString() As String
Return Description
End Function


Why? Someone can tell me?

Thanks in advance.

Comment from Loas at Tuesday, 07 November 2006 05:21PM (GMT+00)

Re: A VB.Net equivalent of ComboBox.ItemData

Loas,

I'm not sure, but as far as I can tell when you set the .Text property of the ComboBox it trys to select the option with the same name. As a result it is looping through all of the objects you have added calling to check if the result of ToString() is the same as the string you are setting .Text to.

From what you have said it is hard for me to tell why this is an issue? Maybe you could expand a little?

Comment from Martin Brown at Friday, 10 November 2006 06:10PM (GMT+00)

Re: A VB.Net equivalent of ComboBox.ItemData

Ok.. let me try explain with my poor English....

When I try to show 3 or 4 diferents combos with the informations from a table, the code became slow.. because pass trought all code again.. you know?

But if it is as you are telling me.. there is nothing to do...

Anyway.. I understood your explanation.

Thanks for your time.

Comment from Loas at Monday, 13 November 2006 10:49AM (GMT+00)

Re: A VB.Net equivalent of ComboBox.ItemData

This is GREAT! for me, it reduces a trip to my database. Previously, when someone clicked the dropdown, I looked up the "ID" associated with that item. Now, the ID is built right into the ComboBox.

Any idea how many records this will hold in this manner? Where does it actually store this id?

Very nice.

Comment from Craig at Tuesday, 23 January 2007 03:59PM (GMT+00)

Re: A VB.Net equivalent of ComboBox.ItemData

Craig: I'm guessing the data is stored inside the DataValueField member.

Question: I tried this method listed and I'm also getting an error in the Add call as follows:

"Overload resolution failed because no accessible 'Add' can be called with these arguments:
'Public Sub Add(item As System.Web.UI.WebControls.ListItem)': Value of type 'ValueDescriptionPair' cannot be converted to 'System.Web.UI.WebControls.ListItem'.
'Public Sub Add(item As String)': Value of type 'ValueDescriptionPair' cannot be converted to 'String'."

Any ideas? My actual call is:
cmbProjects.Items.Add(New ValueDescriptionPair(2, "First Item"))

I placed the class above my existing class on the same page.

Comment from Andy at Friday, 16 February 2007 01:02AM (GMT+00)

Re: A VB.Net equivalent of ComboBox.ItemData

I also tried this code I found elsewhere, that does essentially the same thing, but I still get the same error. Is it possible that it has to do something with the fact that I am not using WinForms, but rather this is in the server side VB code of a web page?

----------- Another approach I tried ---------

Public Class MyList
' This is a class to associate the code and Id with data for a ComboBox or ListBox
Private sName As String
Private iID As Integer

' Default empty constructor.
Public Sub New()
sName = ""
iID = 0
End Sub

Public Sub New(ByVal Name As String, ByVal ID As Integer)
sName = Name
iID = ID
End Sub

Public Property Name() As String
Get
Return sName
End Get
Set(ByVal sValue As String)
sName = sValue
End Set
End Property

' This is the property that holds the extra data.
Public Property ItemData() As Int32
Get
Return iID
End Get
Set(ByVal iValue As Int32)
iID = iValue
End Set
End Property

' This is neccessary because the ListBox and ComboBox rely
' on this method when determining the text to display.
Public Overrides Function ToString() As String
Return sName
End Function
End Class

Comment from Andy at Friday, 16 February 2007 01:07AM (GMT+00)

Re: A VB.Net equivalent of ComboBox.ItemData

First of all sry for my bad english

I have 1 problem....
I need to add items to a ListBox (the name and the itemdata or Id)
But i cant do it by hard (like the example above):

ComboBox1.Items.Add(New ValueDescriptionPair(1, "California"))

I have the name and the Id in a DataSet wich was previously filled, So in one colum of the DataSet i have "Eadm_Id" and in the other "Eadm_Name"...and i dont know hoy to pass them to the ListBox...can anyone help me?

Thanks in advance, =)

Comment from Martin at Monday, 05 March 2007 04:37AM (GMT+00)

Re: A VB.Net equivalent of ComboBox.ItemData

Martin to attach to a DataSet you need to use code like this instead:

' 1st Set the field you wish to display on screen
ComboBox1.DisplayMember = "FieldName1"

' 2nd Set the filed you wish to have ComboBox.SelectedValue set to
ComboBox1.ValueMember = "FieldName2"

' 3rd Set the DataTable you wish to bind to
ComboBox1.DataSource = dataSet.Tables(n)

Comment from MArtin Brown at Monday, 05 March 2007 10:42AM (GMT+00)

It doesn't work in asp.net

It doesn't work in asp.net

Error : System.Web.UI.WebControls.ListItem' cannot be converted to 'ItemData'.

Why?

Comment from rg at Sunday, 01 April 2007 09:50PM (GMT+00)

Re: A VB.Net equivalent of ComboBox.ItemData

I am fairly new to VB.net and I have implemented this code and it works well for adding data to a listbox. But:
1) how do I remove selected items from the listbox?
* one other note is that I may have only 6 items moved to the listbox but the values may be random numbers from 0 to about 200 . I am parsing a rather large line of data and wish to remember the location on the line of where the data is located.
2) I have a checked listbox which I move the checked items to the normal listbox. This works once. but when I remove all items from the normal listbox "because I can't seem to remove the selected items" it doesn't function any longer. My code is getting rather lengthy to paste here.

Comment from Dennis L Lokken at Tuesday, 03 July 2007 01:20AM (GMT+00)

Sorry, this post is no longer accepting comments.