Search code examples
.netvb.netwinformscombobox

Assigning a value to ComboBox Items


I'm currently trying to make a drop box (Combobox) for currencies for a winform. Here's what I have so far:

Screen grab of combobox input

But I noticed that there is a special option for the Databound version of a drop down box. So I was wondering if it was possible to create something similar to this without resorting to do a comparison against the entire string or creating a table in a database.

Screen shot of combobox tasks


Solution

  • List and Comboboxes can contain objects rather than simply strings. Rather than defining the contents in the Designer, you can set a List(Of T) (among others) as the DataSource. This allows you to display one thing but fetch a different thing such as a value back.

    This is so useful, it is not uncommon to have a simple NameValuePair class to translate a value or code into something user-friendly:

    Public Class NVP
        Public Property Name As String
        Public Property Value As Integer
    
        Public Sub New(n As String, v As Integer)
            Name = n
            Value = v
        End Sub
    
        ' what these will display using .ToString:
        Public Overrides Function ToString() As String
            Return String.Format("{0} ({1})", Name, Value.ToString)
        End Function
    End Class
    

    Then the code to create a list of these and use it as the source for the combo:

    Private myAList As List(Of NVP)
    ...
    myAList = New List(Of NVP)
    
    myAList.Add(New NVP("ziggy", 26))
    myAList.Add(New NVP("able", 1))
    myAList.Add(New NVP("charlie", 3))
    myAList.Add(New NVP("echo", 5))
    
    ComboBox1.DataSource = myAList
    ComboBox1.DisplayMember = "Name"    ' property name to show the user
    ComboBox1.ValueMember = "Value"     ' property name to use as the value
    

    Then, using it:

    Console.WriteLine("Selection Changed! Item: {0}  Value: {1}",
                       ComboBox1.SelectedItem.ToString,
                       ComboBox1.SelectedValue.ToString)
    

    Output:

    Selection Changed! Item: ziggy (26) Value: 26
    Selection Changed! Item: charlie (3) Value: 3
    Selection Changed! Item: able (1) Value: 1

    Notes:
    The benefit to the NameValuePair class is that it keep the data together (and easily accessed) rather then as separate items in different arrays.

    The major benefit to using a DataSource, is that you do not need to make a copy of the data. Rather than copy the Name values from the list to the Items collection, the List/ComboBox uses the same ones that your code does.

    SelectedItem returns an NVP object (as does .Items(n)) but they are returned as Object so you need to cast it back to NameValuePair to access any properties:

    thisItem = CType(ComboBox1.SelectedItem, NVP)
    Console.WriteLine(thisItem.Name)
    

    SelectedItem.ToString invokes the ToString method on our Type. It might simply print the Name or whatever you want.

    If the list is dynamic - things get added and/or removed from it - then you will probably want to use a BiningList(of T) instead. Changes to the list will automatically appear in the control (ListBox, ComboBox, DatagridView).

    If the list items are dynamic - {"ziggy", 26} might be changed to {"zulu", 98}, then your item class should implement INotifyPropertyChanged so those changes also automatically show in the UI control.