Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I dynamically change auto complete entries in a C# combobox or textbox?

I had the same problem, and found an extremely simple workaround. As everybody else here, I couldn't find any means to control de behaviour of the component, so I had to accept it.

The natural behaviour is: you can't dynamically populate the list every time the user types into the text box. You have to populate it once, and then the AutoComplete mechanism takes control. The conclusion is: you should populate the AutoCompleteCustomSource with every possible entry in you database to make it work as we want.

Of course this is not viable if you have millions of records to populate the list. Performance issues in data transfer and the AutoComplete mechanism itself will not allow you to do that.

The compromise solution I found was: dynamically populate the AutoCompleteCustomSource every time that the Text length reaches exactly N chars (3 in my case). This worked because complexity was drastically reduced. The number of records that are fetched from the database that match these 3 initial chars was small enough to avoid any performance issues.

The major drawback is: users will not be presented the AutoComplete list until they type the N-th char. But it seems like users don't really expect a meaningful AutoComplete list before 3 chars are typed.

Hope this helps.


This worked for me, you don't addRange to the same AutoCompleteStringCollection, but rather create a new one each time.

form.fileComboBox.TextChanged += (sender, e) => {
    var autoComplete = new AutoCompleteStringCollection();
    string[] items = CustomUtil.GetFileNames();
    autoComplete.AddRange(items);
    form.fileComboBox.AutoCompleteCustomSource = autoComplete;
};

I think you might want to get out the reflector and look at overriding the autocomplete behaviour in the combobox itself. I'm certain the autocompletion would call a function which accesses the autocomplete list. If you can find this function and override it, you can use any behaviour you want.

See what documentation you can find on the combobox class itself.


I haven't test this, but it may be worth a shot.

Instead of clearing the AutoCompleteCustomSource, double buffer by keeping two instances. When the text changes, call GetNameSuggestions() and build the strings for the one that's not currently being used, then set ComboName.AutoCompleteCustomSource to the one you just set up.

I think it should look something like this.

AutoCompleteCustomSource accs_a;
AutoCompleteCustomSource accs_b;
bool accs_check = true; //true for accs_a, false for accs_b
void InitializeComboBox()
{
    ComboName.AutoCompleteMode = AutoCompleteMode.SuggestAppend;
    ComboName.AutoCompleteSource = AutoCompleteSource.CustomSource;

    accs_a = new AutoCompleteStringCollection();
    accs_b = new AutoCompleteStringCollection();

    ComboName.AutoCompleteCustomSource = accs_a;
    ComboName.TextChanged += new EventHandler( ComboName_TextChanged );
}

void ComboName_TextChanged( object sender, EventArgs e )
{
    string text = this.ComboName.Text;

    if(accs_check)
    {
       accs_b.Clear();
       accs_b.AddRange(GetNameSuggestions( text ));
       accs_check = false;
    }
    else
    {
       accs_a.Clear();
       accs_a.AddRange(GetNameSuggestions( text ));
       accs_check = true;
    }

    this.ComboQuery.AutoCompleteCustomSource = accs_check? accs_a : accs_b;
}