I have a combo box in C #, and I want to use automatically complete sentences with it, however I want to be able to change automatically filled records by user type, because the allowed valid records are too numerous to fill in AutoCompleteStringCollection at startup.
As an example, suppose I allow the user to enter a name. I have a list of possible first names ("Joe", "John") and a list of last names ("Bloggs", "Smith"), but if I have a thousand, it will be a million possible lines - too many to add autocomplete. Therefore, at first I want to have only the first names as sentences ("Joe", "John"), and then, as soon as the user types the first name ("Joe"), I want to delete the existing automatically completed records and replace them with a new set, consisting of the selected first name, followed by possible surnames ("Joe Bloggs", "Joe Smith"). For this, I tried the following code:
void InitializeComboBox() { ComboName.AutoCompleteMode = AutoCompleteMode.SuggestAppend; ComboName.AutoCompleteSource = AutoCompleteSource.CustomSource; ComboName.AutoCompleteCustomSource = new AutoCompleteStringCollection(); ComboName.TextChanged += new EventHandler( ComboName_TextChanged ); } void ComboName_TextChanged( object sender, EventArgs e ) { string text = this.ComboName.Text; string[] suggestions = GetNameSuggestions( text ); this.ComboQuery.AutoCompleteCustomSource.Clear(); this.ComboQuery.AutoCompleteCustomSource.AddRange( suggestions ); }
However, this does not work properly. It seems that calling Clear () forces the car to “turn off” until the next character appears in the combo box, but, of course, when the next character appears, the above code will call Clear () again, so the user never actually sees the automatic full functionality. This also causes the entire contents of the combo box to be selected, so between each keystroke you must deselect the existing text, which makes it unusable. If I delete the Clear () call, then autocomplete works, but it seems that the AddRange() call has no effect, because the new offers that I add do not appear in the auto-complete drop-down list.
I searched for a solution to this and saw different things, but I can’t get them to work - either the automatic full functionality is turned off, or new lines are not displayed. Here is a list of things I've tried:
- Call
BeginUpdate() before changing the lines and EndUpdate() after. - Call
Remove() for all existing rows instead of Clear (). - Removing text from the drop-down list when updating rows and adding it back.
- Setting
AutoCompleteMode to "None" when I change lines, and then back to "SuggestAppend" again. - Acquiring a
TextUpdate or KeyPress event instead of TextChanged . - Each time replacing an existing
AutoCompleteCustomSource with a new AutoCompleteStringCollection .
None of them helped, even in various combinations. Spence suggested that I try to override the ComboBox function, which gets a list of strings for automatic completion. Using a reflector, I found several methods in the ComboBox class that look promising - GetStringsForAutoComplete() and SetAutoComplete() , but they are both private, so I cannot access them from a derived class. I could no longer do this.
I tried replacing ComboBox with TextBox because the autocomplete interface is the same and I found that the behavior is a little different. It works better with TextBox , because the part of the Append autocomplete works correctly, but it doesn’t work in the "Suggestion" section - the suggestion window briefly flashes and then immediately disappears.
So, I thought: “Okay, I’ll live without the“ Suggest ”functionality and just use the“ Add ”), however, when I install AutoCompleteMode in the Append, I get an access violation exception. The same thing happens with the sentence - the only mode which does not throw exceptions is SuggestAppend , even though part of the sentence is not behaving correctly.
I thought that when using managed code in C # it was impossible to get access violation exceptions. Avram suggested using a “lock” to fix this, but I don’t know what I should block - the only thing the SyncRoot member has is an AutoCompleteStringCollection and a lock that does not prevent access violation exceptions. I also tried blocking a ComboBox or TextBox , but that didn't help either. As I understand it, locking only prevents other locks, so if the base code does not use locking, then my use of this will not make any difference.
The bottom line of all this is that I cannot use TextBox or ComboBox with dynamic auto-completion. Does anyone know how I can achieve this?
Update:
I still don’t have a job, but I learned something else. Perhaps some of them will inspire someone else to come up with a solution.
I tried replacing ComboBox with TextBox because the autocomplete interface is the same and I found that the behavior is a little different. It works better with TextBox , because the part of the Append autocomplete works correctly, but it doesn’t work in the "Suggestion" section - the suggestion window briefly flashes and then immediately disappears.
So, I thought, “Okay, I will live without the Suggest function and just use the Append instead,” however, when I install AutoCompleteMode in the Append, I get an access violation exception. The same thing happens with a sentence - the only mode that does not throw exceptions is SuggestAppend , even though part of the sentence does not behave correctly.
I thought that when using C # managed code, an exception was thrown due to access violation, but in any case, the result is that I can not use TextBox or ComboBox with any type of dynamic auto-completion. Does anyone know how I can achieve this?
Update 2:
Having tried various other things, such as changing autocomplete in the BeginInvoke() and using BeginInvoke() to model behavior like PostMessage (), I finally gave up and just implemented my own automatic full drop-down list using the list box. This is much more responsive than the built-in, and I spent less time on it than trying to get the built-in to work, so the lesson for everyone who wants this behavior is probably better for you to implement it yourself.