VB.NET下拉框 - 数字值的自动完成行为

7

我在使用VB.NET(.NET框架2.0)中的组合框时,出现了自动完成行为的问题。

我正在使用组合框来输入数字值,并使用其下拉列表来建议可能的数字值。此列表按升序排序,例如{"10","92","9000","9001"}。

组合框属性设置如下:

  • AutoCompleteMode:SuggestAppend
  • AutoCompleteSource:ListItems
  • DropDownStyle:DropDown
  • Sorted:False

下拉列表只是这样填充的:

  • myCombobox.Items.Add("10")
  • myCombobox.Items.Add("92")
  • myCombobox.Items.Add("9000")
  • myCombobox.Items.Add("9001")

当我不输入任何内容时,下拉列表中的值顺序是正确的,按原始/升序排列。但是,当我开始输入时,下拉列表中建议的值被排序(按字母数字顺序):如果我键入“9”,建议的值列表变为{"9000","9001","92"}。

我想避免这种行为,以获得列表中原始/升序排列的值。但我无法想出如何做到...

一个可能的解决方法是在列表中填充值时使用零进行填充,例如{"0010","0092","9000","9001"},但我想避免这种方法。

编辑:

如bendataclear所建议的,可以使用列表框来显示建议。这适用于小型列表,但无法很好地扩展到大型列表。它可能对某些应用程序有用。根据bendataclear给出的代码,我是这样做的:

Private Sub ComboBox1_KeyUp(sender As System.Object, e As System.Windows.Forms.KeyEventArgs) Handles ComboBox1.KeyUp

    Dim cursorPos As Integer = ComboBox1.SelectionStart

    ListBox1.Items.Clear()

    For Each s In ComboBox1.Items
        If s.StartsWith(ComboBox1.Text) Then
            ListBox1.Items.Add(s)
        End If
    Next

    If ListBox1.Items.Count > 0 And ComboBox1.Text.Length > 0 Then
        ComboBox1.Text = ListBox1.Items(0)
        ComboBox1.SelectionStart = cursorPos
        ComboBox1.SelectionLength = 0
    End If

End Sub

这段代码并未经过充分的测试,可以进行改进,但主要思路已经在其中。

编辑2:

使用DataGridView可以提高性能;对我来说已经足够了。感谢bendataclear。

仅出于好奇,欢迎提供其他答案 :)

1个回答

3

当组合框显示数据时似乎存在一个问题,即使你设置了自定义源,它也会按字母顺序重新排序:

ComboBox1.Items.Add("10")
ComboBox1.Items.Add("92")
ComboBox1.Items.Add("9000")
ComboBox1.Items.Add("9001")

ComboBox1.AutoCompleteCustomSource.Add("10")
ComboBox1.AutoCompleteCustomSource.Add("92")
ComboBox1.AutoCompleteCustomSource.Add("9000")
ComboBox1.AutoCompleteCustomSource.Add("9001")

ComboBox1.AutoCompleteSource = AutoCompleteSource.CustomSource

我想到的唯一方法是创建自己的自动完成(未经测试):
Dim cbotxt As String = ComboBox1.Text
Dim key As String

key = ChrW(e.KeyCode)


ListBox1.Items.Clear()

For Each i In ComboBox1.Items

    Dim s As String = i.ToString()

    If s.StartsWith(ComboBox1.Text & key) Then

        ListBox1.Items.Add(s)


    End If

Next

If ListBox1.Items.Count > 0 Then
    ListBox1.Visible = True
    ComboBox1.Text = ListBox1.Items(0)

End If

编辑:

对于许多项目而言,一个好的方法是(我在应用程序中使用了10000+):

首先将列表框更改为数据网格视图。 然后声明一个字符串列表,并填充需要自动完成的值。

 Dim Numberlist as List<Of String>

' Fill List using Numberlist.Add("String")

然后在文本中更改属性:

Filter = NumberList.FindAll(AddressOf checkNum)

DataGridView1.DataSource = Filter

并且添加检查字符串的功能。

Function checkNum(ByVal b As String) As Boolean

    If b.StartsWith(ComboBox1.Text) Then
        Return True
    Else
        Return False
    End If

End Function

这种方法在我的电脑上可以快速地处理10k个项目,速度比我打字还要快。

感谢bendataclear。这确实是一种解决方法。但是当项目列表增长时,速度会变慢。也许可以使用哈希映射来预先构建所有可能的项目列表,具体取决于在组合框中输入的文本,从而避免每次都遍历整个列表。我发现找不到更简单的方法很令人惊讶...我已经将您的解决方案添加到问题中。 - DevelBD
可以这样做。字符串必须包装在自定义类中,否则 DataGridView 只会显示字符串的长度(请参见 https://dev59.com/pnRB5IYBdhLWcg3w4bGv)。在我的计算机上,它适用于 10k 个项目,并且对于 100k 个项目来说速度相当快。谢谢! - DevelBD

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接