.net 如何异步获取文本框的自动完成数据?
我们的WinForms应用程序延迟加载数据以自动完成文本框。这方面的伪代码如下所示.net 如何异步获取文本框的自动完成数据?,.net,winforms,autocomplete,.net,Winforms,Autocomplete,我们的WinForms应用程序延迟加载数据以自动完成文本框。这方面的伪代码如下所示 文本框中的用户类型 键入pause时,确定是否需要获取自动完成的数据 在工作线程中,联系服务器并获取数据 调用回UI线程 设置textBox.AutoCompleteCustomSource=fetchedAutoCompleteStringCollection 强制文本框下拉它的自动完成下拉列表 我目前在#6方面有问题。作为一个黑客,我做了以下工作来模拟一个可以工作的按键,但它并不是在所有情况下都能工作
textBox.AutoCompleteCustomSource=fetchedAutoCompleteStringCollection代码>
// 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调用以导致自动完成下拉列表。如果必须的话,我不介意PinVok退出。通常,您会使用COM互操作并访问或接口。不幸的是,这些方法都没有强制自动完成下拉的方法
您可能希望使用Spy++并查看在显示自动完成时发送到控件的windows消息。您可能会找到一条命令消息来激活它。当然,这是一个实现细节,但这可能是唯一的方法。我已经为一个只使用托管代码的文本框编写了一个异步自动完成类。希望能有帮助
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);
}
我没有试过你的代码,但看起来不错,所以我会接受它作为答案。谢谢
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;
}
}
}
...
TextBox myTextbox = new TextBox();
MockAutoCompleteSource autoComplete =
new MockAutoCompleteSource(myTextbox);
...