我在 C# 中有一个组合框,我想使用自动完成建议,但是我希望能够在用户键入时更改自动完成条目,因为可能的有效条目太多而无法AutoCompleteStringCollection
在启动时填充。
例如,假设我让用户输入名称。我有一个可能的名字列表(“Joe”、“John”)和一个姓氏列表(“Bloggs”、“Smith”),但如果我每个都有一千个,那么这将是一百万个可能的字符串 -太多,无法放入自动完成条目。因此,最初我只想将名字作为建议 ("Joe", "John") ,然后一旦用户输入了名字 ("Joe"),我想删除现有的自动完成条目并替换他们有一个新的集合,包括选择的名字和可能的姓氏(“Joe Bloggs”、“Joe Smith”)。为了做到这一点,我尝试了以下代码:
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 );
}
但是,这不能正常工作。似乎对 Clear() 的调用会导致自动完成机制“关闭”,直到下一个字符出现在组合框中,但是当然当下一个字符出现时,上面的代码再次调用 Clear(),所以用户永远不会实际上看到了自动完成功能。它还会导致组合框的全部内容被选中,因此在每次按键之间您必须取消选择现有文本,这使其无法使用。如果我删除对 Clear() 的调用,则自动完成工作,但似乎AddRange()
调用无效,因为我添加的新建议不会出现在自动完成下拉列表中。
我一直在寻找解决方案,并看到了各种建议,但我无法让它们中的任何一个工作 - 自动完成功能似乎被禁用,或者没有出现新字符串。这是我尝试过的事情的清单:
BeginUpdate()
在更改字符串之前和EndUpdate()
之后调用。- 调用
Remove()
所有现有字符串而不是 Clear()。 - 在我更新字符串时从组合框中清除文本,然后将其添加回来。
- 在我更改字符串时将其设置
AutoCompleteMode
为“None”,然后将其设置回“SuggestAppend”。 - 挂钩
TextUpdate
orKeyPress
事件而不是TextChanged
. - 每次都
AutoCompleteCustomSource
用新的替换现有的。AutoCompleteStringCollection
这些都没有帮助,即使是各种组合。 Spence建议我尝试覆盖ComboBox
获取要在自动完成中使用的字符串列表的函数。使用反射器,我在ComboBox
类中发现了一些看起来很有希望的方法 -GetStringsForAutoComplete()
和SetAutoComplete()
,但它们都是私有的,因此我无法从派生类访问它们。我不能再进一步了。
我尝试用 替换ComboBox
,TextBox
因为自动完成界面是相同的,我发现行为略有不同。它似乎工作得更好,因为TextBox
自动完成的附加部分工作正常,但建议部分没有 - 建议框短暂地闪烁,然后立即消失。
所以我想“好吧,我会在没有 Suggest 功能的情况下生活,而只使用 Append”,但是当我将其设置AutoCompleteMode
为 Append 时,我得到了访问冲突异常。Suggest 也会发生同样的事情 - 唯一不会引发异常的模式是SuggestAppend
,即使 Suggest 部分的行为不正确。
我认为使用 C# 托管代码时应该不可能出现访问冲突异常。 Avram建议我使用“锁定”来解决此问题,但我不知道我应该锁定什么 - 唯一具有 SyncRoot 成员的是AutoCompleteStringCollection
, 并且锁定不会阻止访问冲突异常。我也尝试锁定ComboBox
or TextBox
,但这也无济于事。据我了解, lock 只会阻止其他锁,所以如果底层代码没有使用 lock 那么我使用它不会有任何区别。
所有这一切的结果是我目前无法使用动态自动完成的 aTextBox
或 a 。ComboBox
有人对我如何实现这一目标有任何见解吗?
更新:
我还没有得到这个工作,但我发现了更多。也许其中一些会激发其他人提出解决方案。
我尝试用 替换ComboBox
,TextBox
因为自动完成界面是相同的,我发现行为略有不同。它似乎工作得更好,因为TextBox
自动完成的附加部分工作正常,但建议部分没有 - 建议框短暂地闪烁,然后立即消失。
所以我想“好吧,我会在没有 Suggest 功能的情况下生活,而只是使用 Append”,但是当我将其设置AutoCompleteMode
为 Append 时,我得到了访问冲突异常。Suggest 也会发生同样的事情 - 唯一不会引发异常的模式是SuggestAppend
,即使 Suggest 部分的行为不正确。
我认为在使用 C# 托管代码时应该不可能获得访问冲突异常,但无论如何,结果是我目前无法使用 aTextBox
或 aComboBox
任何类型的动态自动完成。有人对我如何实现这一目标有任何见解吗?
更新 2:
在尝试了各种其他事情(例如更改工作线程中的自动完成功能,并BeginInvoke()
用于模拟 PostMessage() 类型的行为之后,我终于放弃了,只是使用列表框实现了我自己的自动完成下拉菜单。它比内置的响应速度更快,而且我花在这方面的时间比我试图让内置的工作的时间少,所以任何想要这种行为的人的教训是 - 你可能会更好自己实施。