Combo Box items - Display Member for List(Of String)?

我与影子孤独终老i 提交于 2019-12-26 03:47:00

问题


My project is in Visual Basic. I am trying to create a custom & savable "filter" for a DataGridView using several TextBoxes. Right now, any List(Of String) that is added to the Combo Box is displayed in the box as (Collection). I want my users to be able to select the one they created, so I would like the Lists to have a display name that can be selected in the Combo Box. Here is some of the code.

Dim savedFilter As New List(Of String)
savedFilter.Add(NameTextBox.Text)
savedFilter.Add(AgeTextBox.Text)
savedFilter.Add(NotesTextBox.Text)
ComboBoxSavedFilters.Items.Add(savedFilter)

Is it possible to add a display name for a List?


回答1:


Or if you are lazy use buid-in generic class Tuple From MSDN.

Create collection of Tuple(Of String, List(Of String)) and use approach suggested by @Plutonix for binding collection to ComboBox

Dim savedFilter As New List(Of Tuple(Of String, List(Of String)))()
savedFilter.Add(
    Tuple.Create("default",
                 New List From {"filter1", "filter2", "filter3"}))
savedFilter.Add(
    Tuple.Create("Blue ones", 
                 New List From {"filter4", "filter5"}))
savedFilter.Add(
    Tuple.Create("Old ones", 
                 New List From {NameTextBox.Text, AgeTextBox.Text, NotesTextBox.Text}))

With ComboBoxSavedFilters
    .DisplayMember = "Item1" 'Name of first property in Tuple type
    .ValueMember = "Item2" 'Name of second property in Tuple type -List 
    .DataSource = savedFilter       
End With

Then SelectedValue will contain currently selected filter's collection, which can be accessed like that

Dim filter As List(Of String) =
    DirectCast(Me.ComboBoxSavedFilters.SelectedValue, List(Of String))



回答2:


You could setup under My.Settings a StriingCollection

Initializing (you can omit the items added if so desired)

If My.Settings.Filters Is Nothing Then
    My.Settings.Filters = New StringCollection() From {"One", "Two"}
End If

Setup items in a ComboBox

ComboBox1.Items.AddRange(My.Settings.Filters.Cast(Of String).ToArray)

Adding an item

My.Settings.Filters.Add(Now.ToShortDateString)

You can remove and clear items too.




回答3:


Provide a Display Member for List(Of String)

Apparently, these are less a collection of filters than a collection of criteria or clauses for one Filter:

I condensed the code in the question, but there are 14 fields that can be filtered and there are multiple filters that can be applied on one field.

For the multiples per field, I am not sure I would want to store those individually, but keep the field criteria together. So, if you want to apply a name to these, a class would not only do that but could help manage the filter elements:

Public Class SuperFilter
    Public Property Name As String
    Public Property Elements As SortedList

    Public ReadOnly Property FilterText As String
        Get
            Return GetFilterText()
        End Get
    End Property

    Public Sub New(n As String)
        Name = n
        Elements = New SortedList
    End Sub

    Public Sub AddItem(filter As String)
        Elements.Add(Elements.Count, filter)
    End Sub

    Public Sub InsetAt(index As Int32, filter As String)
        Elements.Add(index, filter)
    End Sub

    Private Function GetFilterText() As String
        Dim els(Elements.Count - 1) As String
        Elements.Values.CopyTo(els, 0)

        Return String.Join(" ", els)
    End Function

    Public Overrides Function ToString() As String
        Return String.Format("{0} ({1})", Name, Elements.Count.ToString)
    End Function
End Class

You would need to add methods and properties like Remove and Count but this should be enough to demonstrate. I am not sure about the SortedList, a Dictionary using the field name might be better, but something to control the order seems worthwhile. I am also unsure I would expose the Elements collection - managing it might be better left to the class.

Hopefully, the Combo displaying a set of these (as opposed to the filter elements/clauses) is the goal.

Private filters As New List(Of SuperFilter)

Add filter items to the list:

Dim item As New SuperFilter("Default")
item.AddItem("Id = 7")
filters.Add(item)

item = New SuperFilter("Blue Ones")
item.AddItem("Color = Blue")
filters.Add(item)

item = New SuperFilter("Complex")
item.AddItem("[Name] like %Bob% OR [Name] like %Alice%")
item.AddItem("AND Color = 'Blue'")
item.AddItem("AND Active=True")
item.AddItem("AND AccessRequired < 3")
item.AddItem("AND DateAdded > #2/11/2010#")
item.AddItem("AND CreatedBy = 'ziggy'")
filters.Add(item)

cbo1.DataSource = filters
cbo1.DisplayMember = "Name"
cbo1.ValueMember = "FilterText"

The value member could be the Elements - the collection of filter clauses, or it could be the query text. The GetFilterText method joins them together for you as part of what a filter manager class could/should:

    For n As Int32 = 0 To filters.Count - 1
        Console.WriteLine("Name: {0}   Count: {1}{2}Text:{3}", filters(n).Name,
                            filters(n).Elements.Count,
                            Environment.NewLine, filters(n).FilterText)
    Next

Result:

Name: Default Count: 1
Text:Id = 7
Name: Blue Ones Count: 1
Text:Color = Blue
Name: Complex Count: 6
Text:[Name] like %Bob% OR [Name] like %Alice% AND Color = 'Blue' AND Active=True AND AccessRequired < 3 AND DateAdded > #2/11/2010# AND CreatedBy = 'ziggy'

If you use "Elements" as the ValueMember you will get back the collection.

The combo displays the Name for the user. On the right, a label displays the ValueMember in this case, it is the FilterText or joined Elements. As I said, you could get back the actual collection as the SelectedValue instead, but that is available as part of SelectedItem.

If savable means beyond the life of the application instance, that is another question, but these are very easily serialized.



来源:https://stackoverflow.com/questions/35020076/combo-box-items-display-member-for-listof-string

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!