Populating ListBox with List of VB.NET

2019-02-28 10:46发布

问题:

I have a class called optionCode:

Class optionCode
    Public description As String
    Public optCode As String
End Class

I have a query the returns a list of this optionCode class:

Dim _SelectActiveOptionCodes2 = (From _OptCodes In _EntityModel.tblOptionCodes
                                Where _OptCodes.fdStatus = "A"
                                Select New optionCode With {.description = _OptCodes.fdDescription,
                                                            .optCode = _OptCodes.fdOptionCode}).ToList()

I want to use this list to populate a listbox where the description is the display field and the option code is the value field.

When using:

sortableOptionCodes = _SelectActiveOptionCodes2
sortedOptionCodes = _SelectActiveOptionCodes2
OptionCodeListBox.DataSource = sortedOptionCodes

The listbox populates, but every entry is "OptionCodeSearch.Form1+optionCode"

I can't figure out how to use the .ValueMember and .DisplayMember functions to get the listbox to load the way I want.

回答1:

First, ValueMember and DisplayMember work off properties: Gets or sets the property to use as the actual value for the items in the System.Windows.Forms.ListControl. So your class should use Properties not Fields (there are conditions where Fields are treated/handled differently than Properties).

With such classes, it good idea to override ToString so you can specify the default text to display instead of the Type (OptionCodeSearch.Form1+optionCode):

Class optionCode
    Public PROPERTY description As String
    Public PROPERTY optCode As String

    Public Overrides Function ToString() As String
        Return Description       ' ????
    End Function
End Class

ValueMember is typically a numeric, but otherwise once you have the List(of optionCode) ValueMember and DisplayMember are used to tell the ListBox the Property Names:

OptionCodeListBox.DisplayMember = "description"
OptionCodeListBox.ValueMember = "optCode"

Not for nothing, but primitives like that can be made into a generic use-almost-anywhere class:

Public Class Element(Of T)
    Public Property Name As String

    Public Property Value As T

    Friend Sub New(n As String, v As T)
        Name = n
        Value = v
    End Sub

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

End Class

Of T allows you to define the Value data type when you build it:

Dim el As New Element(Of Integer)(textName, intValue)

Your list would then be:

Dim myList As New List(Of Element(Of Integer))

It is a little cumbersome to iterate lists, but VS/Intellisense provide hints:

For Each El As Element(of Integer) in myList(Of Element(Of Integer))

If you are using one of these a lot in a project, you can subclass it:

Public Class optCode
    Inherits Element(Of String)

Now, the whole Element(Of String) part is built into your new optCode class, making it easier to type, use and remember.

The value of these is that you can use the same class for a collection of Name-Value pairs of string, datetime, integer, decimal etc without coding a new class each time you need something like it.



回答2:

Edit: This answer is for the web form control. See Plutonix's answer for the windows form control.

I believe what you are looking for are the DataTextField and DataValueField properties of the ListBox.

OptionCodeListBox.DataTextField = "description"
OptionCodeListBox.DataValueField = "optCode"