如何SuggestAppend包含字符串的ComboBox

时间:2014-10-14 14:01:54

标签: vb.net winforms combobox autocomplete contains

目标

我想让我的ComboBox项目建议并在其中包含某些内容时附加其项目,而不仅仅是通过StartsWith函数。

我的ComboBox绑定到DataView,其中包含长连接中的客户端[ CompanyName ],[地址],[城市]。

我希望我的用户能够输入城市并仍然找到与上述所有字段匹配的记录。我知道这可以通过Infragistics实现,但我没有这个包。

搜索字词:" Sher "

  • Costco,123 1st Avenue, Sher brooke
  • Provigo,344 Ball Street, Sher brooke
  • Sher 框,93 7th Street,Montreal

这可能在VB.Net中使用,还是应该搜索其他内容?

4 个答案:

答案 0 :(得分:6)

我做了一些研究,发现了以下问题:

Override Winforms ComboBox Autocomplete Suggest Rule

在那个问题中,他们回答了另一个问题:

C# AutoComplete

  

让我们引用该问题的最佳答案

     

现有的自动完成功能仅支持搜索   字首。似乎没有任何体面的方式可以覆盖   行为。

     

有些人已经实现了自己的自动完成功能   覆盖OnTextChanged事件。这可能是你最好的选择。

     

例如,您可以在ListBox下方添加TextBox并进行设置   其默认可见性为false。然后你可以使用OnTextChanged   事件的TextBoxSelectedIndexChanged事件   ListBox显示和选择项目。

     

这似乎是一个很好的例子:

public Form1()
{
    InitializeComponent();


    acsc = new AutoCompleteStringCollection();
    textBox1.AutoCompleteCustomSource = acsc;
    textBox1.AutoCompleteMode = AutoCompleteMode.None;
    textBox1.AutoCompleteSource = AutoCompleteSource.CustomSource;
}

private void button1_Click(object sender, EventArgs e)
{
    acsc.Add("[001] some kind of item");
    acsc.Add("[002] some other item");
    acsc.Add("[003] an orange");
    acsc.Add("[004] i like pickles");
}

void textBox1_TextChanged(object sender, System.EventArgs e)
{
    listBox1.Items.Clear();
    if (textBox1.Text.Length == 0)
    {
    hideResults();
    return;
    }

    foreach (String s in textBox1.AutoCompleteCustomSource)
    {
    if (s.Contains(textBox1.Text))
    {
        Console.WriteLine("Found text in: " + s);
        listBox1.Items.Add(s);
        listBox1.Visible = true;
    }
    }
}

void listBox1_SelectedIndexChanged(object sender, System.EventArgs e)
{
    textBox1.Text = listBox1.Items[listBox1.SelectedIndex].ToString();
    hideResults();
}

void listBox1_LostFocus(object sender, System.EventArgs e)
{
    hideResults();
}

void hideResults()
{
    listBox1.Visible = false;
}
     

如果没有太多努力,你可以做更多的事情:追加文字   到文本框,捕获其他键盘命令,等等。

答案 1 :(得分:4)

改进了BenD在他的回答中所展示的技术,以便让机制更优雅地处理某些角落:

public sealed class CCComboboxAutocomplete : ComboBox
{
    public CCComboboxAutocomplete()
    {
        AutoCompleteMode = AutoCompleteMode.Suggest; //crucial otherwise exceptions occur when the user types in text which is not found in the autocompletion list
    }

    protected override void OnTextChanged(EventArgs e)
    {
        try
        {
            if (DesignMode || !string.IsNullOrEmpty(Text) || !Visible) return;

            ResetCompletionList();
        }
        finally
        {
            base.OnTextChanged(e);
        }
    }

    protected override void OnKeyPress(KeyPressEventArgs e)
    {
        try
        {
            if (DesignMode) return;
            if (e.KeyChar == '\r' || e.KeyChar == '\n')
            {
                e.Handled = true;
                if (SelectedIndex == -1 && Items.Count > 0 && Items[0].ToString().ToLowerInvariant().StartsWith(Text.ToLowerInvariant()))
                {
                    Text = Items[0].ToString();
                }
                DroppedDown = false;
                return; //0
            }

            BeginInvoke(new Action(ReevaluateCompletionList)); //1
        }
        finally
        {
            base.OnKeyPress(e);
        }
    }
    //0 Guardclose when detecting any enter keypresses to avoid a glitch which was selecting an item by means of down arrow key followed by enter to wipe out the text within
    //1 Its crucial that we use begininvoke because we need the changes to sink into the textfield  Omitting begininvoke would cause the searchterm to lag behind by one character  That is the last character that got typed in

    private void ResetCompletionList()
    {
        _previousSearchterm = null;
        try
        {
            SuspendLayout();

            var originalList = (object[])Tag;
            if (originalList == null)
            {
                Tag = originalList = Items.Cast<object>().ToArray();
            }

            if (Items.Count == originalList.Length) return;

            while (Items.Count > 0)
            {
                Items.RemoveAt(0);
            }

            Items.AddRange(originalList);
        }
        finally
        {
            ResumeLayout(performLayout: true);
        }
    }

    private string _previousSearchterm;
    private void ReevaluateCompletionList()
    {
        var currentSearchterm = Text.ToLowerInvariant();
        if (currentSearchterm == _previousSearchterm) return; //optimization

        _previousSearchterm = currentSearchterm;
        try
        {
            SuspendLayout();

            var originalList = (object[])Tag;
            if (originalList == null)
            {
                Tag = originalList = Items.Cast<object>().ToArray(); //0
            }

            var newList = (object[])null;
            if (string.IsNullOrEmpty(currentSearchterm))
            {
                if (Items.Count == originalList.Length) return;

                newList = originalList;
            }
            else
            {
                newList = originalList.Where(x => x.ToString().ToLowerInvariant().Contains(currentSearchterm)).ToArray();
            }

            try
            {
                while (Items.Count > 0) //1
                {
                    Items.RemoveAt(0);
                }
            }
            catch
            {
                try
                {
                    Items.Clear();
                }
                catch
                {
                }
            }


            Items.AddRange(newList.ToArray()); //2
        }
        finally
        {
            if (currentSearchterm.Length >= 2 && !DroppedDown)
            {
                DroppedDown = true; //3
                Cursor.Current = Cursors.Default; //4
                Text = currentSearchterm; //5
                Select(currentSearchterm.Length, 0);
            }

            ResumeLayout(performLayout: true);
        }
    }
    //0 backup original list
    //1 clear list by loop through it otherwise the cursor would move to the beginning of the textbox
    //2 reset list
    //3 if the current searchterm is empty we leave the dropdown list to whatever state it already had
    //4 workaround for the fact the cursor disappears due to droppeddown=true  This is a known bu.g plaguing combobox which microsoft denies to fix for years now
    //5 Another workaround for a glitch which causes all text to be selected when there is a matching entry which starts with the exact text being typed in
}

答案 2 :(得分:-3)

ComboBoxTextBox,我认为DropDownList具有自动完成属性 看http://msdn.microsoft.com/en-us/library/system.windows.forms.combobox.autocompletemode(v=vs.110).aspx

它解释了您应该使用哪个AutoCompleteMode以及如何设置AutoCompleteSource

答案 3 :(得分:-3)

您可以尝试以下几行,它对我有用

 cbxName.AutoCompleteMode = AutoCompleteMode.SuggestAppend;
 cbxName.AutoCompleteSource = AutoCompleteSource.ListItems;