7
votes

I have a problem with the auto-complete behaviour of comboboxes in VB.NET (with the .NET framework 2.0).

I am using a combobox to type in numeric values, and its DropDown list to suggest possible numeric values. This list is sorted in ascending order, for example {"10","92", "9000", "9001"}.

The combobox properties are set as follow:

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

The DropDown list is simply filled like this:

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

When I don't type anything, the order of values of the DropDown list is correct, in original/ascending order. However, when I start typing something, the suggested values in the DropDown list get sorted (alphanumerically): if I type "9", the list of suggestions becomes {"9000", "9001", "92"}.

I would like to prevent this behaviour to get the values of the list in the original/ascending order. I can't figure out how...

A possible work-around would be to pad with zeroes the values in the list, e.g. {"0010", "0092", "9000", "9001"} but I would like to avoid this.

Edit:

As suggested by bendataclear, one can use a list box to display the suggestions. This will work for small lists but doesn't scale well to large lists. It may be useful for some applications. Based on the code given by bendataclear, I made it work this way:

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

The code has not been thoroughly tested and can be improved, but the main idea is there.

Edit 2:

Using DataGridView leads to better performance; it was sufficient for me. Thanks bendataclear.

Just out of curiosity, any other answer is welcomed :)

1

1 Answers

3
votes

Seems to be an issue when the combo box displays the data, as even if you set a custom source it re-orders alphabetically:

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

I think the only way I can think of is to create your own autocomplete something like (untested):

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

Edit:

A good approach for many items (I'm using for 10000+ in an application):

First change from a list box to a datagridview. Then declare a list of strings and fill with values you want to autocomplete

 Dim Numberlist as List<Of String>

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

Then in the text change property:

Filter = NumberList.FindAll(AddressOf checkNum)

DataGridView1.DataSource = Filter

And add the function to check the strings.

Function checkNum(ByVal b As String) As Boolean

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

End Function

This method runs on my machine with 10k items faster than I can type.