Our WinForms application does lazy loading of the data for auto complete of a textbox. The pseudocode for this is as follows;
textBox.AutoCompleteCustomSource = fetchedAutoCompleteStringCollection;
I am currently having trouble with #6. As a hack, I do the following to simulate a keypress which works, but it does not work in all situations.
// This is a hack, but the only way that I have found to get the autocomplete
// to drop down once the data is returned.
textBox.SelectionStart = textBox.Text.Length;
textBox.SelectionLength = 0;
SendKeys.Send( " {BACKSPACE}" );
There must be a better way. I can't believe that I am the only person fetching auto complete data asynchronously. How should I be doing this?
EDIT: A Win32 call to cause the Auto Complete to dropdown would be acceptable. I don't mind PInvoking out if I have to.
I have written an async autocomplete class for a TextBox using only managed code. Hope it helps.
using System;
using System.Windows.Forms;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel;
namespace TextboxAutocomplete
{
public abstract class AutoCompleteSource
{
private TextBox mTextBox;
private AutoCompleteMode mAutoCompleteMode;
public AutoCompleteSource(TextBox textbox) :
this(textbox, AutoCompleteMode.Suggest) { }
public AutoCompleteSource(TextBox textbox, AutoCompleteMode mode)
{
if (textbox == null)
throw new ArgumentNullException("textbox");
if (textbox.IsDisposed)
throw new ArgumentException("textbox");
mTextBox = textbox;
mAutoCompleteMode = mode;
mTextBox.AutoCompleteSource = System.Windows.Forms.AutoCompleteSource.None;
BackgroundWorker autoCompleteLoader = new BackgroundWorker();
autoCompleteLoader.DoWork += new DoWorkEventHandler(autoCompleteLoader_DoWork);
autoCompleteLoader.RunWorkerCompleted += new RunWorkerCompletedEventHandler(autoCompleteLoader_RunWorkerCompleted);
autoCompleteLoader.RunWorkerAsync();
}
void autoCompleteLoader_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
AutoCompleteStringCollection collection = e.Result as AutoCompleteStringCollection;
if (collection == null) return;
if (mTextBox.InvokeRequired)
{
mTextBox.Invoke(new SetAutocompleteSource(DoSetAutoCompleteSource), new object[] { collection });
}
else
{
DoSetAutoCompleteSource(collection);
}
}
protected void DoSetAutoCompleteSource(AutoCompleteStringCollection collection)
{
if (mTextBox.IsDisposed) return;
mTextBox.AutoCompleteMode = mAutoCompleteMode;
mTextBox.AutoCompleteSource = System.Windows.Forms.AutoCompleteSource.CustomSource;
mTextBox.AutoCompleteCustomSource = collection;
}
void autoCompleteLoader_DoWork(object sender, DoWorkEventArgs e)
{
List<string> autoCompleteItems = GetAutocompleteItems();
if (autoCompleteItems == null) return;
AutoCompleteStringCollection collection = new AutoCompleteStringCollection();
collection.AddRange(GetAutocompleteItems().ToArray());
e.Result = collection;
}
protected abstract List<string> GetAutocompleteItems();
}
internal delegate void SetAutocompleteSource(AutoCompleteStringCollection collection);
}
Sample implementation:
using System;
using System.Windows.Forms;
using System.Collections.Generic;
using System.Text;
namespace TextboxAutocomplete
{
class MockAutoCompleteSource : AutoCompleteSource
{
public MockAutoCompleteSource(TextBox textbox)
: base(textbox)
{
}
protected override List<string> GetAutocompleteItems()
{
List<string> result = new List<string>();
for (int i = 0; i < 2500; i++)
{
result.Add(Guid.NewGuid().ToString());
}
return result;
}
}
}
How to use it:
...
TextBox myTextbox = new TextBox();
MockAutoCompleteSource autoComplete =
new MockAutoCompleteSource(myTextbox);
...
Typically, you would use COM interop and access the IAutoComplete
, IAutoComplete2
, or the IAutoCompleteDropDown
interface. Unfortunately, none of these has methods to force the autocomplete to drop down.
You might want to use Spy++ and look at the windows messages that are being sent to the control when the auto complete displays. You might find a command message which will activate it. Of course, this is an implementation detail, but it might be the only way to go here.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With