0

I want to show the suggested words using autocomplete for the textbox. For instance, i type Tod... all words from my database that starts with "tod" will show but after I chose a word if i type another word like "was" there will be no suggested words below. Probably because the string collection doesn't have "today was". I want to show suggested words that only starts with "was" not "today was". I am attaining to make a project that predicts the most frequent words used. Here is my code

public partial class Form1 : Form
{
    string[] arr = new string[] { "sn k", "sn k", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sept", "Oct", "Nov", "Dec" };



    public Form1()
    {
        InitializeComponent();

    }

    private void Form1_Load(object sender, EventArgs e)
    {

    }

    private void txtInput_TextChanged(object sender, EventArgs e)
    {
        predict();
    }



    void predict()
    {

        txtInput.AutoCompleteMode = AutoCompleteMode.Suggest;
        txtInput.AutoCompleteSource = AutoCompleteSource.CustomSource;
        AutoCompleteStringCollection col = new AutoCompleteStringCollection();

        col.AddRange(arr);
        txtInput.AutoCompleteCustomSource = col;
    }
}

}

Kat
  • 1
  • 2
  • Possible duplicate of [How to make an auto-complete textbox in a winforms desktop application](https://stackoverflow.com/questions/4629909/how-to-make-an-auto-complete-textbox-in-a-winforms-desktop-application) – Vadim Ovchinnikov Feb 22 '18 at 16:16
  • AutoComplete is pretty dumb and don't have (m)any extensionpoints. If what you need isn't delivered with that you have now roll your own autocomplete but that would be too broad to be answered here. – rene Feb 22 '18 at 16:21
  • The answer you have is correct. You really don't have to recreate a `AutoCompleteCustomSource` every time the TextBox text is changed. You don't even need an `AutoCompleteStringCollection`. `AutoCompleteCustomSource` is already that type, thus you are executing the same operation twice. You could just: `txtInput.AutoCompleteCustomSource.AddRange(arr);` – Jimi Feb 22 '18 at 16:41
  • My problem here is that when I type the second word it doesn't suggest words anymore. For example, I type "J" some choices are suggested below the textbox such as "January" "July" etc. So when I picked January it adds up inside the textbox but when I typed the second word "was" there will be no suggested words are shown. Probably because there is no "January was" from the string collection. I would like to use autocomplete for multiple words inputted inside the textbox if it is possible. – Kat Feb 22 '18 at 19:54

2 Answers2

0

So a basic "Roll Your Own" solution will work like so:

string[] arr = new string[] { "sn k", "sn k", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sept", "Oct", "Nov", "Dec" };

private ListBox autoListBox;

private void Form1_Load(object sender, EventArgs e)
{
    this.txtInput.TextChanged += txtInput_TextChanged;
    CreateAutocompleteListBox();
}

private void txtInput_TextChanged(object sender, EventArgs e)
{
    showAutoCompleteList();
}

private void CreateAutocompleteListBox()
{
    this.autoListBox = new ListBox()
    {
        Left = this.txtInput.Left,
        Top = this.txtInput.Top + this.txtInput.Height,
        Width = 100,
        Height = 75
    };

    this.autoListBox.Click += autoListBox_Click;
    this.autoListBox.KeyDown += autoListBox_KeyDown;
    this.autoListBox.Visible = false;
    this.Controls.Add(this.autoListBox);
}

private void autoListBox_Click(object sender, EventArgs e)
{
    AutocompleteFinished();
}

private void autoListBox_KeyDown(object sender, KeyEventArgs e)
{
    var finishCodes = new List<Keys> { Keys.Return, Keys.Space };
    if (finishCodes.Contains(e.KeyCode))
    {
        AutocompleteFinished();
    }
}

private string GetLastWord(TextBox txt)
{
    return (" " + txt.Text).Split(' ').LastOrDefault() ?? "";
}

private void showAutoCompleteList()
{
    this.autoListBox.Left = this.txtInput.Left;
    this.autoListBox.Top = this.txtInput.Top + this.txtInput.Height + 2;
    var lastWord = GetLastWord(this.txtInput);

    this.autoListBox.Items.Clear();
    this.autoListBox.Items.AddRange(this.arr.Where(aw => aw.ToLower().StartsWith(lastWord.ToLower())).ToArray());
    this.autoListBox.Visible = true;
}

private void txtInput_KeyDown(object sender, KeyEventArgs e)
{
    // These keys show auto-complete selector
    var activatorCodes = new List<Keys> { Keys.Up, Keys.Down };
    if (activatorCodes.Contains(e.KeyCode))
    {
        SwitchToAutoCompleteList();
    }
}

private void SwitchToAutoCompleteList()
{
    this.autoListBox.Focus();
    this.autoListBox.SelectedIndex = 0;
}

private void AutocompleteFinished()
{
    var lastWord = GetLastWord(this.txtInput);
    var nextWord = this.autoListBox.Text;
    this.txtInput.Text = this.txtInput.Text.Substring(0, this.txtInput.Text.Length - lastWord.Length);
    this.txtInput.AppendText(nextWord);
    this.autoListBox.Visible = false;
}

This ought to do what you want, it will show autocomplete for each word! One could add a little finesse, such as moving the autocomplete box around as the text moves on.

Terry Lennox
  • 29,471
  • 5
  • 28
  • 40
  • It works well with mine too. What I want to do is to use the autocomplete for multiple words. For example, if i type "Jan" I will append the january from the suggested word below and then when I type "was" another suggested words will appear that starts with "was" only. – Kat Feb 22 '18 at 19:59
  • Hmmmm.. I don't know if that's possible to do..you will get the suggestion once you accept the first word..it will then reset the autocomplete behaviour. – Terry Lennox Feb 22 '18 at 20:05
  • I am attaining to make a project in c# that predicts the word just by the few first characters inputted by the user only. Just like how the auto prediction in mobile works. – Kat Feb 22 '18 at 20:13
  • Hey @Kat, I've updated the answer with a simple enough autocomplete that will do what you want. – Terry Lennox Feb 22 '18 at 21:29
0

Simplest solution is to implement a custom control based on Textbox that contains Textbox control and a list box control. Using text change event populate list box with strings that match users selection. Focus remains on control not contained control in context of application form. Internally the defined user control must handle any events from contained textbox and list control. List box is displayed only if your autocomplete list contains multiple matches (based on your rules).

If only one match exists it is (conventionally) shown in textbox with "completion" text highlighted where mode is "append". That is not feasible if suggestion is not based on "starts with". Only "suggest" mode can be implemented with other than "starts with". In suggest mode the list box is displayed in all cases where match list is not empty.