我们的WinForms应用程序延迟加载数据以自动完成文本框.伪代码如下:
TextBox中的用户类型
在键入暂停时,确定是否需要获取自动完成数据
在工作线程中,联系服务器并获取数据
调用回UI线程
组 textBox.AutoCompleteCustomSource = fetchedAutoCompleteStringCollection;
强制文本框下拉自动完成下拉菜单.
我目前在#6遇到麻烦.作为一个黑客,我做以下工作来模拟一个有效的按键,但它并不适用于所有情况.
// 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}" );
肯定有更好的办法.我无法相信我是唯一一个异步获取自动完成数据的人.我该怎么做?
编辑: Win32调用导致自动完成下拉是可以接受的.如果必须,我不介意PInvoking.
我只使用托管代码为TextBox编写了一个异步自动完成类.希望能帮助到你.
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) { ListautoCompleteItems = GetAutocompleteItems(); if (autoCompleteItems == null) return; AutoCompleteStringCollection collection = new AutoCompleteStringCollection(); collection.AddRange(GetAutocompleteItems().ToArray()); e.Result = collection; } protected abstract List GetAutocompleteItems(); } internal delegate void SetAutocompleteSource(AutoCompleteStringCollection collection); }
示例实施:
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 ListGetAutocompleteItems() { List result = new List (); for (int i = 0; i < 2500; i++) { result.Add(Guid.NewGuid().ToString()); } return result; } } }
如何使用它:
... TextBox myTextbox = new TextBox(); MockAutoCompleteSource autoComplete = new MockAutoCompleteSource(myTextbox); ...