【问题标题】:Combo Box items - Display Member for List(Of String)?组合框项目 - 列表(字符串)的显示成员?
【发布时间】:2016-01-26 17:31:02
【问题描述】:

我的项目在 Visual Basic 中。我正在尝试使用多个文本框为 DataGridView 创建一个自定义和可保存的“过滤器”。现在,添加到组合框中的任何 List(Of String) 都在框中显示为 (Collection)。我希望我的用户能够选择他们创建的那个,所以我希望列表有一个可以在组合框中选择的显示名称。这是一些代码。

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

是否可以为列表添加显示名称?

【问题讨论】:

    标签: vb.net list combobox


    【解决方案1】:

    或者如果你很懒,使用内置泛型类TupleFrom MSDN

    创建Tuple(Of String, List(Of String)) 的集合并使用@Plutonix 建议的方法将集合绑定到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
    

    然后SelectedValue 将包含当前选择的过滤器的集合, 可以这样访问

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

    【讨论】:

    • 这个问题是我只想指定一个字符串来显示整个列表。当我只想为整个列表设置一个值时,我觉得这会为组合框中的每个字段设置一个值。
    • @MattLeverich,只需将第二个属性的类型更改为List(Of String),第一个属性将包含过滤器集合的显示名称,第二个属性包含集合本身
    • 另外,为了展开,我希望用户能够在组合框中输入他们想要的过滤器列表名称,然后按回车键保存
    • 因为我有一个“保存”按钮,可以将保存的过滤器添加到列表中,出于某种原因,即使我可以看到它的 DataSource 正在显示所有这些值,ComboBox 也只会显示第一个值。那里有什么问题?
    【解决方案2】:

    您可以在 My.Settings 下设置一个 StriingCollection

    正在初始化(如果需要,您可以省略添加的项目)

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

    在组合框中设置项目

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

    添加项目

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

    您也可以删除和清除项目。

    【讨论】:

      【解决方案3】:

      为 List(Of String) 提供显示成员

      显然,这些不是过滤器的集合,而是一个过滤器的标准或子句的集合:

      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.

      对于每个字段的倍数,我不确定是否要单独存储它们,但将字段条件保持在一起。所以,如果你想为这些应用一个名字,一个类不仅可以做到这一点,而且可以帮助管理过滤器元素:

      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
      

      您需要添加诸如RemoveCount 之类的方法和属性,但这应该足以演示。我不确定SortedList,使用字段名称的Dictionary 可能会更好,但控制顺序的东西似乎值得。我也不确定我是否会公开 Elements 集合 - 管理它可能最好留给班级。

      希望显示一组这些(而不是过滤器元素/子句)的 Combo 是目标。

      Private filters As New List(Of SuperFilter)
      

      将过滤器项添加到列表中:

      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"
      

      值成员可以是Elements - 过滤子句的集合,也可以是查询文本。 GetFilterText 方法将它们连接在一起,作为过滤器管理器类可以/应该做的一部分:

          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
      

      结果:

      名称:默认计数:1
      文本:Id = 7
      名称:Blue Ones 数量:1
      文本:颜色 = 蓝色
      名称:复杂计数:6
      文本:[Name] like %Bob% OR [Name] like %Alice% AND Color = 'Blue' AND Active=True AND AccessRequired #2/11/2010# AND CreatedBy = 'ziggy'

      如果您使用“元素”作为 ValueMember,您将取回集合。

      组合显示用户的Name。在右侧,标签显示ValueMember,在这种情况下,它是FilterText 或加入Elements。正如我所说,您可以将实际集合取回为 SelectedValue,但这可以作为 SelectedItem 的一部分使用。

      如果savable 意味着超出应用程序实例的生命周期,那就是另一个问题了,但这些很容易序列化。

      【讨论】:

      • 我压缩了问题中的代码,但是有14个字段可以过滤,并且可以在一个字段上应用多个过滤器。过滤是在 SQL 中完成的,因此如果您选择对“名称”执行两个过滤器,即您将“Bob”放在一个文本框中,将“Alice”放在下面的一个文本框中,SQL 查询将是“...WHERE [姓名] 喜欢 %Bob% 或 [姓名] 喜欢 %Alice%”。这些自定义过滤器需要保存,每个文本框值(包括“”)都保存在 List(Of String) 中,然后放入 ComboBox,但我需要一个名称附加到该列表而不是 (Collection )
      • 此外,ComboBox 也不需要执行过滤器 - 这已经使用 TextBoxes 中的 Text_Changed 事件完成,因此 DataGridView 过滤器会在您更改 TextBoxes 中的值时生效
      • 没有什么是我提供的。过滤器可以像您可以处理的那样简单或复杂。它提供的功能元素是为它们分配名称。 Text_Changed 不适合应用过滤器
      • 其实是一个名为concat()的方法,使用SQL进行过滤
      • 我按照你说的做了,ComboBox 填充了列表中的每个字段,而不仅仅是一个值来表示整个列表。我做错了什么?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-26
      • 1970-01-01
      • 2017-11-17
      • 1970-01-01
      相关资源
      最近更新 更多