文本框自动完成无法正常工作

3
我正在尝试使用自定义数据源(数组)实现文本框自动完成,在单个字符输入时显示建议。但是,当我运行程序时,只有在输入第二个字符后,自动完成才会启动。我调试时发现AutoCompleteNameCollection中存在数据,但在建议中没有显示,直到第二个字符输入。 我在textchange事件中编写了以下代码。
arr = LoadName(empid_txt.Text.Trim());  //arr is string array                          
namesCollection.AddRange(arr);
this.empid_txt.AutoCompleteMode = AutoCompleteMode.Suggest;
this.empid_txt.AutoCompleteSource = AutoCompleteSource.CustomSource;
this.empid_txt.AutoCompleteCustomSource = namesCollection;

在LoadEvent中,我已经使用空数组初始化了AutoCompleteNameCollection。
namesCollection.AddRange(arr);// here arr is empty
empid_txt.AutoCompleteMode = AutoCompleteMode.Suggest;
empid_txt.AutoCompleteSource = AutoCompleteSource.CustomSource;
empid_txt.AutoCompleteCustomSource = namesCollection;

但是直到输入第二个字符才起作用。但如果我用空字符串初始化AutoCompleteNameCollection,例如:namesCollection.Add(""); 它可以在单个字符输入时起作用,但有时会出现AccessViolationException: Attempted to read or write protected memory的问题。那么有没有办法解决这个问题呢?

我在使用文本框时遇到了同样的问题,因为我使用了多行文本框,这导致了这个问题。将多行属性改为false解决了这个问题。 - Huzaifa
5个回答

2

当在事件处理程序中设置AutoCompleteSource时,我可以复制访问冲突错误。似乎自动完成例程可能正在替换和销毁AutoCompleteSource时访问它。

为了防止这种情况,您可以在代码周围加锁。

lock(this)
{
arr = LoadName(empid_txt.Text.Trim());  //arr is string array                          
namesCollection.AddRange(arr);
this.empid_txt.AutoCompleteMode = AutoCompleteMode.Suggest;
this.empid_txt.AutoCompleteSource = AutoCompleteSource.CustomSource;
this.empid_txt.AutoCompleteCustomSource = namesCollection;
}

这样做可以防止访问违规。


1

AutoComplete 在第二个字符被按下后才会建议,这是正常的,因为首先,您已将 arr(即您的自定义数据源)初始化为空数组。您在 TextChanged 事件中填充了您的 arr,这就是为什么 AutoComplete 在第二个字符上起作用的原因,因为您的数据源是基于第一个字符进行过滤的(这绝对不是您想要的)。

以下是一个建议:

  • 在应用程序的 FormLoad 事件中,使用所有可能的建议填充 arr我认为建议来源于数据库,对吗?)。这将允许文本框在输入第一个字符时进行建议。

  • 当您输入第一个字符时,在 TextChanged 事件中重新加载您的 arr 数据源,基于之前输入的字符。

希望能有所帮助。


我不想把所有东西都放在表单加载事件中...当要检索的数据量很大时,它会导致太多的网络拥塞和带宽需求,因此我只使用文本更改事件...此外,正如我所说,当我在表单加载事件中首先用空字符串初始化它,然后在文本更改事件中将数据源更改为字符串数组时,它确实适用于单个字符输入...但它并不稳定,因为有时会出现上述异常。是的,数据源实际上是一个数据库。 - Nav

1

在加载时,您可以使用数据的子集(甚至可以缓存以供将来/共享使用)填充TextBox。如果您有一个“最常见”的计数器,可以使用它。作为限制条件,您甚至可以添加一个虚拟项目(如果使用空字符串会导致访问冲突)。 然后,在TextChange事件中从数据库中读取所需的数据。

我只有一个问题:您不想在用户开始输入之前填充源吗?如果存在网络流量问题,则会移动大量数据。如果移动大量数据,则用户在开始输入时必须等待。这是可以接受的吗?另一方面,如果他们不需要等待太久,也许数据流不是很大,您可以将该逻辑放在表单构造函数的BackgroundWorker中(或者离那个时间不远)。


0
在窗体加载时调用文本框自动完成方法。
 public void autocompleteData()
    {
            //SuggestStrings will have the logic to return array of strings either from cache/db
            var CurrentuserId = CloudKaseWSClient.GetUserDetail(tokenUsr, tokenPasswd, Username);
            List<string> l = new List<string>();
            var SearchResults = ("Select Database Query").ToList();
            foreach (var i in SearchResults)
            {
                l.Add(i.name);
            }
            string[] arr = l.ToArray();
            AutoCompleteStringCollection collection = new AutoCompleteStringCollection();
            collection.AddRange(arr);

        txtSearchUser.AutoCompleteMode = AutoCompleteMode.SuggestAppend;
        txtSearchUser.AutoCompleteSource = AutoCompleteSource.CustomSource;
        txtSearchUser.AutoCompleteCustomSource = collection;
    }

如果您想为自动完成文本框设置静态数据,那么您需要在设计视图中为AutocompleteMode的文本框属性设置SuggestAppend,AutocompleteSource设置为CustomSource,并将静态值添加到AutocompleteCustomSource中。

我希望这个解决方案能对您有所帮助。 编程愉快。 :)


0
如果在初始化文本框时'arr'为空,则没有可比较的内容。在开始输入之前,您必须将AutoCompleteCustomSource初始化为有效的数组。您正在textchange事件中进行初始化,而此时用户已经键入了一个字符。
您需要在Initialize中填充namesCollection,以便在代码更改之前完成。

你是在要求我在用户开始输入之前加载所有数据吗?如果是这样,我做不到,因为有很多数据可以在文本更改事件中进行筛选。 - Nav
只有当输入框有匹配项时,才能使用自动完成功能。由于在用户输入内容之前你无法填充数据源,因此第一个字符不会自动完成。你可以尝试过滤上游事件(例如KeyDown事件)。 - Raj Ranjhan
但是当我最初用一个空字符串而不是一个字符串数组来填充源并在文本更改时将其替换/追加到一个字符串数组中时,它确实有效... 但是有时会出现访问冲突异常。您知道有什么解决方法吗? - Nav

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接