带有数据库驱动的自动完成的WinForms(C#)输入字段

时间:2015-05-09 16:44:42

标签: c# winforms combobox autocomplete textchanged

我正在尝试使用自动完成功能创建文本输入字段。可用选项列表很大(50,000+),需要在TextChanged上查询(在输入前3个字符后)。

我有一个99%的TextBox工作解决方案,在TextChanged事件中将AutoCompleteCustomSource设置为我的新AutoCompleteStringCollection,但由于基础AutoComplete实现中存在明确记录的错误,导致偶尔的内存访问违规...

Microsoft Support说"不要在关键事件期间动态修改自动完成候选列表" ...

多个SO主题:123

这些主题有一些关于如何防止异常的建议,但似乎没有什么可以完全消除它们,所以我正在寻找替代方案。尝试过切换到基于ComboBox的解决方案,但不能让它按照我的意愿行事。

  • 用户输入第三个字符后,我会更新ComboBox的数据源,但会自动选择第一个项目。用户无法继续键入其余名称。

  • 在用户点击三角形以展开列表之前,ComboBox项目不可见

  • 如果用户选择他们输入的文本并开始输入,我将DataSource设置为null以删除建议列表。这样做会将光标放在文本的开头,因此它们的字符显示的顺序完全错误!

我的观点:

    public event EventHandler SearchTextChanged;
    public event EventHandler InstrumentSelected;

    public Instrument CurrentInstrument
    {
        get { return comboBoxQuickSearch.SelectedItem as Instrument; }
    }

    public IEnumerable<Instrument> Suggestions
    {
        get { return comboBoxQuickSearch.DataSource as IEnumerable<Instrument>; }
        set
        {
            comboBoxQuickSearch.DataSource = value;
            comboBoxQuickSearch.DisplayMember = "Name";
        }
    }

    public string SearchText
    {
        get { return comboBoxQuickSearch.Text; }
    }

    private void comboBoxQuickSearch_TextChanged(object sender, EventArgs e)
    {
        if (SearchTextChanged != null)
        {
            SearchTextChanged(sender, e);
        }
    }

    private void comboBoxQuickSearch_KeyDown(object sender, KeyEventArgs e)
    {
        if (e.KeyCode == Keys.Enter && InstrumentSelected != null)
        {
            InstrumentSelected(sender, e);
        }
    }

我的演示者:

    private void SearchTextChanged(object sender, EventArgs e)
    {
        lock (searchLock)
        {
            // Do not update list of suggestions if:
            // 1) an instrument has already been selected
            //    (the user may be scrolling through suggestion list)
            // 2) a search has taken place within the last MIN_SEARCH_INTERVAL
            if (DateTime.Now - quickSearchTimeStamp < minimumSearchInterval
                || (view.Suggestions != null && view.Suggestions.Any(i => i.Name == view.SearchText)))
            {
                return;
            }

            string searchText = view.SearchText.Trim();
            if (searchText.Length < SEARCH_PREFIX_LENGTH)
            {
                // Do not show suggestions
                view.Suggestions = null;
                searchAgain = false;
            }
            // If the prefix has been entered or changed,
            // or another search is needed to display the full sublist
            else if (searchText.Length == SEARCH_PREFIX_LENGTH
                  || searchText.Substring(0, SEARCH_PREFIX_LENGTH) != searchTextPrefix
                  || searchAgain)
            {
                // Record the current time and prefix
                quickSearchTimeStamp = DateTime.Now;
                searchTextPrefix = searchText.Substring(0, SEARCH_PREFIX_LENGTH);

                // Query matches from DB
                IList<Instrument> matches = QueryMatches(searchText);

                // Update suggestions
                view.Suggestions = matches;

                // If a large number of results was received, search again on the next chararacter
                // This ensures the full match list is presented
                searchAgain = matches.Count() > MAX_RESULTS;
            }
        }
    }

(searchAgain位留在TextBox实现中,如果AutoCompleteCustomSource包含的项目太多,AutoCompleteCustomSource将不会显示完整列表。)

我可以按照我的意愿让ComboBox工作,根据我在TextChanged上查询这些建议的要求,提供用户输入的建议吗?

我是否应该使用其他一些控件组合来获得更好的用户体验,例如:列表框?

0 个答案:

没有答案