6

I would like to have a DisplayMember and a ValueMember on a ComboBox which has only 4 values and they are always the same.

Is it possible without using a DataTable as DataSourceand without creating a class?

I would like to have something like:

ValueMember= "Fixed"  
DisplayMember= "Specific and unique number"

ValueMember= "Multiple"  
DisplayMember= "Multiple and different numbers"

ValueMember= "Repeated"  
DisplayMember= "One number repeated x times"
Ňɏssa Pøngjǣrdenlarp
  • 38,411
  • 12
  • 59
  • 178
genespos
  • 3,211
  • 6
  • 38
  • 70

5 Answers5

10

Fundamentally, you cant do what you want:

ValueMember= "Fixed"  
DisplayMember= "Specific and unique number"

Value- and DisplayMember are not for specifying the literal values, but are used to indicate the Property Names in something else (like a class).


Without using a DataSource (title) is not the same as not using a class (question text). There are alternatives to creating a class:

Existing NET Types

You could use the existing NET KeyValuePair class to link a value with a name:

cbox.Items.Add(New KeyValuePair(Of String, String)("Specific", 
         "Specific and unique number"))
cbox.Items.Add(New KeyValuePair(Of String, String)("Multiple", 
         "Multiple and different numbers"))
cbox.Items.Add(New KeyValuePair(Of String, String)("Repeated", 
         "One number repeated x times"))

cbox.ValueMember = "Key"
cbox.DisplayMember = "Value"

There is no DataSource - the data is in the items collection. There is also Tuple as explained in another answer


Anonymous Type

Using one string as the key for another string is a quite odd. Typically in code you would want something less prone to errors from typos. Typing "Fized" somewhere breaks your code. An Enum makes much more sense:

Private Enum ValueStyle
    Specific = 0
    Multiple = 1
    Repeated = 2
End Enum

Now, you can create a List which links a description for the user and the Enum constants:

' fuller text descr of the enum for the user
Dim descr As String() = {"Specific and unique number",
                         "Multiple and different numbers",
                         "One number repeated x times"}
' get enum values into an array of ValueStyle
Dim values = [Enum].GetValues(GetType(ValueStyle)).Cast(Of ValueStyle).ToArray

' create a List of anon objects from the descr() and values()
Dim lst = values.Select( Function (q) New With
                       {.Value = q, .Name = descr (q)}
                    ).ToList()
    
cboPicker.ValueMember = "Value"
cboPicker.DisplayMember = "Name"
cboPicker.DataSource = lst

This creates an Anonymous Type - an object without a class - with a Name and Value property mapped to the Enum and description array. If the Enum values are not sequential (e.g. {8, 65, 99}), the list would have to be built differently.

This creates a temporary collection of Anonymous Type objects and assigns it as the DataSource. You wont be able to access the Name and Value properties in other methods because anonymous type cant be passed to other methods. But the user will see the desired text and NET/VB will provide the value as that enum as the SelectedValue. Using the SelectedValue changed event:

' name user sees == cboPicker.Text
' value == cboPicker.SelectedValue boxed as Object

Dim userChoice As ValueStyle = CType(cboPicker.SelectedValue, ValueStyle)
If userChoice = ValueStyle.Specific Then
    '...
ElseIf userChoice = ValueStyle.Repeated Then
    '...
End If

Notice that rather than testing "Fixed" as a string, the code uses the enum but is still every bit as readable.

MSDN: Anonymous Types (Visual Basic)


Those fit the criteria of not needing a new class, but consider:

Friend Class NameValuePair
    Public Property Name As String
    Public Property Value As Int32

    Public Sub New(n As String, v As Int32)
        Name = n
        Value = v
    End Sub

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

End Class

The class is very simple and is almost infinitely reusable in associating any Name with any Value. It could be used with any number of list based controls, in any number of projects. The code to create and use a list of them is simpler than using the other methods.

Community
  • 1
  • 1
Ňɏssa Pøngjǣrdenlarp
  • 38,411
  • 12
  • 59
  • 178
3

Using some class is a solution, but because you don't want use custom class - use build-in type.

Dim values As New List(Of Tuple(Of String, String))()
values.Add(New Tuple("Fixed", "Specific and unique number"))
values.Add(New Tuple("Multiple", "Multiple and different numbers"))
values.Add(New Tuple("Repeated", "One number repeated x times"))
'and so on...

combobox.ValueMember = "Item1"
combobox.DisplayMember = "Item2"
combobox.DataSource = values

Tuple(Of T1, T2) Class

But for sake of readability my advise use custom class.
Or just in case of reusing custom class is better than Tuple

Fabio
  • 31,528
  • 4
  • 33
  • 72
0

cbActive is a combobox

Private Sub LoadActiveCB()

    Dim _Active As New List(Of ActiveCB)

    _Active.Add(New ActiveCB With {.Name = "Fixed", .ID = 1})
    _Active.Add(New ActiveCB With {.Name = "Multiple", .ID = 2})
    _Active.Add(New ActiveCB With {.Name = "Repeated", .ID = 3})

    cbActive.DataSource = _Active
    cbActive.DisplayMember = "Name"
    cbActive.ValueMember = "ID"

End Sub

Class ActiveCB
    Property Name As String
    Property ID As Byte
End Class

You'll have to tweak it a bit, change the display and value members, but I believe this may be what you want...?

bstarr
  • 33
  • 6
0

I think I get it now... Maybe something like:

Public Class Form1
    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Dim comboSource As New Dictionary(Of String, String)()
        comboSource.Add("1", "Sunday")
        comboSource.Add("2", "Monday")
        comboSource.Add("3", "Tuesday")
        comboSource.Add("4", "Wednesday")
        comboSource.Add("5", "Thursday")
        comboSource.Add("6", "Friday")
        comboSource.Add("7", "Saturday")
        ComboBox1.DataSource = New BindingSource(comboSource, Nothing)
        ComboBox1.DisplayMember = "Value"
        ComboBox1.ValueMember = "Key"
    End Sub
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim key As String = DirectCast(ComboBox1.SelectedItem, KeyValuePair(Of String, String)).Key
        Dim value As String = DirectCast(ComboBox1.SelectedItem, KeyValuePair(Of String, String)).Value
        MessageBox.Show(key & "   " & value)
    End Sub
End Class

Credit: http://net-informations.com/q/faq/combovalue.html

bstarr
  • 33
  • 6
0

Given a IList of anonymous types pointing to a database entities in VB, I use it to build an anonymous list with one member pointing to the db entity object (PO) and another to a composite of the values in the entity (Display):

Dim aList = _BO_Data.Lines
       .Select(Function(PO) ew With {.ACBond = PO, .Display = (PO.Product.Code_item & " - " & PO.Product.Descr)}).ToList()

Combobox_Code_Product.DataSource = aList
Combobox_Code_Product.DisplayMember = "Display"
Combobox_Code_Product.ValueMember = "ACBond"

Then the combobox SelectedItem is the ACBond object and the what I see in the list is the mix of the code and the description of the product.

Alex Alvarez
  • 371
  • 3
  • 6