Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
784 views
in Technique[技术] by (71.8m points)

.net - Set DisplayMember and ValueMember on ComboBox without DataSource

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"
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...