如何在C#组合框或文本框中动态更改自动完成条目?

时间:2009-02-05 11:49:11

标签: c# winforms autocomplete combobox textbox

14 个答案:

答案 0 :(得分:13)

我遇到了同样的问题,并找到了一个非常简单的解决方法。和其他人一样,我找不到任何方法来控制组件的行为,所以我不得不接受它。

自然行为是:每次用户键入文本框时,都无法动态填充列表。您必须填充一次,然后AutoComplete机制将获得控制权。结论是:您应该使用数据库中的每个可能条目填充AutoCompleteCustomSource,以使其按预期工作。

当然,如果您有数百万条记录来填充列表,那么这是不可行的。数据传输中的性能问题和自动完成机制本身不允许您这样做。

我发现的折衷解决方案是:每次文本长度恰好达到N个字符时动态填充AutoCompleteCustomSource(在我的情况下为3)。这很有效,因为复杂性大大降低了。从数据库中提取的与这3个初始字符匹配的记录数量足够小,可以避免任何性能问题。

主要缺点是:在键入第N个字符之前,用户不会显示自动完成列表。但似乎用户在输入3个字符之前并不真正期望有意义的自动完成列表。

希望这有帮助。

答案 1 :(得分:2)

这对我有用,你没有addRange到同一个AutoCompleteStringCollection,而是每次创建一个新的。{/ p>

form.fileComboBox.TextChanged += (sender, e) => {
    var autoComplete = new AutoCompleteStringCollection();
    string[] items = CustomUtil.GetFileNames();
    autoComplete.AddRange(items);
    form.fileComboBox.AutoCompleteCustomSource = autoComplete;
};

答案 2 :(得分:1)

我认为你可能想要反射出来并看看覆盖组合框本身的自动完成行为。我确定自动完成会调用一个访问自动完成列表的函数。如果您可以找到此功能并覆盖它,则可以使用您想要的任何行为。

查看您在combobox类本身上可以找到的文档。

答案 3 :(得分:1)

我没有测试过,但它可能值得一试。

通过保留两个实例,而不是清除AutoCompleteCustomSource,双缓冲区。当文本更改时,调用GetNameSuggestions()并为当前未使用的字符串构建字符串,然后将ComboName.AutoCompleteCustomSource设置为您刚刚设置的字符串。

我认为它看起来应该是这样的。

AutoCompleteCustomSource accs_a;
AutoCompleteCustomSource accs_b;
bool accs_check = true; //true for accs_a, false for accs_b
void InitializeComboBox()
{
    ComboName.AutoCompleteMode = AutoCompleteMode.SuggestAppend;
    ComboName.AutoCompleteSource = AutoCompleteSource.CustomSource;

    accs_a = new AutoCompleteStringCollection();
    accs_b = new AutoCompleteStringCollection();

    ComboName.AutoCompleteCustomSource = accs_a;
    ComboName.TextChanged += new EventHandler( ComboName_TextChanged );
}

void ComboName_TextChanged( object sender, EventArgs e )
{
    string text = this.ComboName.Text;

    if(accs_check)
    {
       accs_b.Clear();
       accs_b.AddRange(GetNameSuggestions( text ));
       accs_check = false;
    }
    else
    {
       accs_a.Clear();
       accs_a.AddRange(GetNameSuggestions( text ));
       accs_check = true;
    }

    this.ComboQuery.AutoCompleteCustomSource = accs_check? accs_a : accs_b;
}

答案 4 :(得分:0)

更新: 把锁放在这个地方的主要原因是

它的工作:) 在这个技巧消失之后,我所拥有的大部分“神秘异常”


  1. 此代码中的锁可以帮助您解决异常
  2. 如前所述,
  3. 使用textbox
  4. 的问题较少
  5. 在此代码中,SuggestAppend正常工作

  6.     private void Form1_Load(object sender, EventArgs e)
        {
            textBox1.AutoCompleteMode = AutoCompleteMode.SuggestAppend;
            textBox1.AutoCompleteSource = AutoCompleteSource.CustomSource;
    
            textBox1.TextChanged+=new EventHandler(textBox1_TextChanged);
    
            col1.AddRange(new string[] { "avi avi", "avram avram" });
            col2.AddRange(new string[] { "boria boria", "boris boris" });
    
            textBox1.AutoCompleteCustomSource = col1;
            textBox1.AutoCompleteMode = AutoCompleteMode.SuggestAppend;
        }
        AutoCompleteStringCollection col1 = new AutoCompleteStringCollection();
        AutoCompleteStringCollection col2 = new AutoCompleteStringCollection();
    
        object locker = new object();
        private void textBox1_TextChanged(object sender, EventArgs e)
        {
            lock (locker)
            {
                if (textBox1.Text.StartsWith("a") && textBox1.AutoCompleteCustomSource != col1)
                {
                    textBox1.AutoCompleteCustomSource = col1;
                }
                if (textBox1.Text.StartsWith("b") && textBox1.AutoCompleteCustomSource != col2)
                {
                    textBox1.AutoCompleteCustomSource = col2;
                }
            }
        }
    

答案 5 :(得分:0)

if(!textBox3.AutoCompleteCustomSource.Contains(textBox3.Text))
   textBox3.AutoCompleteCustomSource.Add(textBox3.Text);

答案 6 :(得分:0)

山姆,你弄清楚了吗?我遇到了同样的情况。 Clear()似乎导致异常。我删除了要求清除的电话,但我收到了正确的建议事件,尽管该集合一直在增长...

此外,关于私人成员:您可以使用反射访问它们:

PropertyInfo[] props = [object].GetType().GetProperties({flags go here});
props[0].SetValue(this, new object[] { 0 });

答案 7 :(得分:0)

我最初是来这里寻找解决方案,但现在找到了自己的解决方案。

技巧不是在AutoCompleteCustomSource上调用Clear(),而是删除for循环中的所有项目,然后使用新数据重建列表。在我的情况下(书籍收集应用程序)我正在从具有特定起始字母的数据库中检索作者姓名,而不是整个批次。请注意,这仅在组合框的文本框部分已空或已变空时才有效。

    private void cboAuthor_KeyDown(object sender, KeyEventArgs e)
    {
        if (cboAuthor.Text.Length == 0)
        {
            // Next two lines simple load data from the database in the
            // into a collection (var gateway), base on first letter in
            // the combobox. This is specific to my app.
            var gateway = new AuthorTableGateway();
            gateway.LoadByFirstLetter(Char.ConvertFromUtf32(e.KeyValue)[0]);

            // Clear current source without calling Clear()
            for (int i = 0; i < authorsAutoComplete.Count; i++)
                authorsAutoComplete.RemoveAt(0);

            // Rebuild with new data
            foreach (var author in gateway)
                authorsAutoComplete.Add(author.AuthorName);
        }
    }

答案 8 :(得分:0)

请勿尝试此操作,但针对您的具体情况,您可以使用以下代码进行编码:

    private void txtAutoComplete_KeyUp(object sender, KeyEventArgs e)
    {

        String text = txtAutoComplete.Text;

        if (text.EndsWith(" "))
        {

            string[] suggestions = GetNameSuggestions( text ); //put [text + " "] at the begin of each array element
            txtAutoComplete.AutoCompleteCustomSource.Clear();
            txtAutoComplete.AutoCompleteCustomSource.AddRange( suggestions );

        }

    }

答案 9 :(得分:0)

对我来说,秘密是使用TextChanged事件而没有使用KeyDown / Up / Press等。

更新:在遇到动态更改AutoCompleteCustomSource的其他问题后,我最终放弃使用内置的自动填充功能,并在比我最初浪费的时间短得多的时间内实现了自己的功能。在实现ComboBox控件的非托管代码中似乎存在一些问题。具体来说,我遇到了TextChanged事件处理程序触发的问题。我决定只在我的自定义实现中使用OnKeyDown / Press / Up处理程序,这似乎更可靠。

答案 10 :(得分:0)

最好的解决方案是使用组合框的事件处理程序。通过使用 textUpdate KeyDown DropDown ChangeCommit ,您可以模仿autocompletemode,您可以自定义要搜索的内容以及下拉列表中显示的内容。

我发现this答案很有用,但它是用visual c ++编写的,它是toolstripcombobox但概念是相同的。无论如何,.net中的c#和c ++有很大的相似之处,理解解决方案应该不是问题。

Customized Autosearch of ToolStripCombobox in Visual C++

答案 11 :(得分:0)

这是我所知道的一个非常古老的问题,但它仍然存在于今天。 我的解决方法是将自动完成模式和源属性设置为“无”,并手动更新KeyUp事件上的项目。

我确信这很糟糕,但无论数据输入的速度如何,它都能在没有问题的情况下完美地为我工作,而且我的头发开始重新增加了额外的奖励。

您还可以选择是仅建议,还是建议和追加。 我希望它可以帮助别人。

private void comboBox1_KeyUp(object sender, KeyEventArgs e)
    {

        if (string.IsNullOrWhiteSpace(comboBox1.Text))
        {
            e.Handled = true;
            return;
        }
        if (comboBox1.Text.Length < 3)
        {
            e.Handled = true;
            return;
        }

        if (e.KeyCode == Keys.Down || e.KeyCode == Keys.Up)
        {
            e.Handled = true;
            return;
        }
        else if (e.KeyCode == Keys.Back)
        {
            e.Handled = true;
            return;
        }

        string text = comboBox1.Text;

        if (e.KeyCode == Keys.Enter)
        {
            comboBox1.DroppedDown = false;
            comboBox1.SelectionStart = text.Length;
            e.Handled = true;
            return;
        }

        List<string> LS = Suggestions(comboBox1.Text);

        comboBox1.Items.Clear();
        comboBox1.Items.AddRange(LS.ToArray());

        //If you do not want to Suggest and Append
        //comment the following line to only Suggest
        comboBox1.Focus();

        comboBox1.DroppedDown = true;
        comboBox1.SelectionStart = text.Length;

        //Prevent cursor from getting hidden
        Cursor.Current = Cursors.Default;
        e.Handled = true;
    }

答案 12 :(得分:0)

尝试了这里提供的所有解决方案后(没有成功),我发现了一些对我有用的东西:

private void CellBox_TextChanged(object sender, EventArgs e)
{
    ((TextBox)sender).TextChanged -= CellBox_TextChanged;
    ((TextBox)dataGridView1.EditingControl).AutoCompleteMode = AutoCompleteMode.None;
    ((TextBox)dataGridView1.EditingControl).AutoCompleteCustomSource = null;                
    aCSC.Clear();
    foreach (string value in Autocompletevalues())
    {
        aCSC.Add(value);
    }
    ((TextBox)dataGridView1.EditingControl).AutoCompleteCustomSource = aCSC;
    ((TextBox)dataGridView1.EditingControl).AutoCompleteMode = AutoCompleteMode.Suggest;
    ((TextBox)sender).TextChanged += CellBox_TextChanged;
}

步骤:

  • 禁用事件处理程序
  • 禁用自动完成模式
  • 将Source设置为null
  • 更新AutoCompleteStringCollection(aCSC)
  • 将“源”设置为更新的AutoCompleteStringCollection
  • 激活自动完成模式
  • 启用事件处理程序

我希望它可以帮助某人。

答案 13 :(得分:-2)

使用此代码

private void dataGridView1_EditingControlShowing(object sender,DataGridViewEditingControlShowingEventArgs e)
    {

        if (e.Control is DataGridViewComboBoxEditingControl)
        {
            ((ComboBox)e.Control).DropDownStyle = ComboBoxStyle.DropDown;
            ((ComboBox)e.Control).AutoCompleteSource = AutoCompleteSource.ListItems;
            ((ComboBox)e.Control).AutoCompleteMode = System.Windows.Forms.AutoCompleteMode.Suggest;
        }

}