Click here to Skip to main content
15,892,927 members
Articles / Programming Languages / C#
Tip/Trick

IntelliSense TextBox in C#

Rate me:
Please Sign up or sign in to vote.
4.92/5 (11 votes)
3 Mar 2014CPOL2 min read 50K   3.2K   32   6
Auto Word Completion for Multiline Textbox (Minimal Intellisense)
Image 1

Introduction

IntelliSense is nothing but a feature to predict the word when we are typing the starting letter of the word. We all are using Visual Studio, there we are typing the class name or namespace name, Visual Studio automatically shows the object list which holds the member & methods of that class / namespace.

This tip will definitely be useful to you to make your own IntelliSense TextBox in C#. This not a perfect IntelliSense but it has minimal ability to handle the auto word completion.

System Design

The system design of this application is very easily understandable. When we are entering text in TextBox, the popup listbox shows the list of starting letters of the last word in the string. The popup listbox items are loaded from the dictionary list which we created for the application. If the last word is not matching with list elements, the popup menu hides.

Image 2

The popup menu should be shown the downside of the text line so here we need to get the text cursor position. For that, we need to call private extern static int GetCaretPos(out Point p) function of user32.dll assembly.

Using the Code

The AutoCompleteTextBox is the method for making IntelliSense for the given TextBox.

AutoCompleteTextBox Method

C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Drawing;
using System.Windows.Forms;

namespace IntellisenceTextBox
{
    class clsIntelliSense
    {
        [DllImport("user32")]
        private extern static int GetCaretPos(out Point p);

        /// <summary>
        /// <para>AutoCompleteTextBox is the method to popups when typing the keywords on TextBox to avoid the mistakes.</para>
        /// <para>Type 1:</para>
        /// <para>&#160;&#160;&#160;&#160;List&lt;string&gt; 
        ISList = new List&lt;string&gt;(new string[] { "SELECT", "CREATE", "TABLE" }); </para>
        /// <para>&#160;&#160;&#160;&#160;AutoCompleteTextBox(textBox1,listBox1, ISList,e);</para>
        /// <para></para>
        /// <para>Type 2:</para>
        /// <para>&#160;&#160;&#160;&#160;AutoCompleteTextBox(textBox1,listBox1,
        new List&lt;string&gt;(new string[] { "SELECT", "CREATE", "TABLE" }),e);</para>
        /// <para></para>
        /// <para>Type 3:</para>
        /// <para>&#160;&#160;&#160;&#160;AutoCompleteTextBox(textBox1,listBox1,
        new string[] { "SELECT", "CREATE", "TABLE" }.ToList(),e);</para>
        /// <para>Note: Don't Use Two Words in Dictionary List. Ex. "AUDI CAR" </para>
        /// </summary>
        /// <param name="txtControl">Text Box Name</param>
        /// <param name="lstControl">List Box Name</param>
        /// <param name="lstAutoCompleteList">Dictionary List</param>
        /// <param name="txtControlKEA">Text Box Key Up Event Args.</param>
        /// 
        public static void AutoCompleteTextBox(TextBox txtControl, ListBox lstControl, 
            List<string> lstAutoCompleteList, KeyEventArgs txtControlKEA)
        {
            Point cp;
            GetCaretPos(out cp);
            List<string> lstTemp = new List<string>();
            //Positioning the Listbox on TextBox by Type Insertion Cursor position
            lstControl.SetBounds(cp.X + txtControl.Left, cp.Y + txtControl.Top + 20, 150, 50);

            var TempFilteredList = lstAutoCompleteList.Where
                (n => n.StartsWith(GetLastString(txtControl.Text).ToUpper())).Select(r => r);

            lstTemp = TempFilteredList.ToList<string>();
            if (lstTemp.Count != 0 && GetLastString(txtControl.Text) != "")
            {
                lstControl.DataSource = lstTemp;
                lstControl.Show();
            }
            else
            {
                lstControl.Hide();
            }

            //Code for focusing ListBox Items While Pressing Down and UP Key. 
            if (txtControlKEA.KeyCode == Keys.Down)
            {
                lstControl.SelectedIndex = 0;
                lstControl.Focus();
                txtControlKEA.Handled = true;
            }
            else if (txtControlKEA.KeyCode == Keys.Up)
            {
                lstControl.SelectedIndex = lstControl.Items.Count - 1;
                lstControl.Focus();
                txtControlKEA.Handled = true;
            }

            //text box key press event
            txtControl.KeyPress += (s, kpeArgs) =>
            {

                if (kpeArgs.KeyChar == (char)Keys.Enter)
                {
                    if (lstControl.Visible == true)
                    {
                        lstControl.Focus();
                    }
                    kpeArgs.Handled = true;
                }
                else if (kpeArgs.KeyChar == (char)Keys.Escape)
                {
                    lstControl.Visible = false;
                    kpeArgs.Handled = true;
                }
            };

            //listbox keyup event
            lstControl.KeyUp += (s, kueArgs) =>
            {
                if (kueArgs.KeyCode == Keys.Enter)
                {
                    string StrLS = GetLastString(txtControl.Text);
                    int LIOLS = txtControl.Text.LastIndexOf(StrLS);
                    string TempStr = txtControl.Text.Remove(LIOLS);
                    txtControl.Text = TempStr + ((ListBox)s).SelectedItem.ToString();
                    txtControl.Select(txtControl.Text.Length, 0);
                    txtControl.Focus();
                    lstControl.Hide();
                }
                else if (kueArgs.KeyCode == Keys.Escape)
                {
                    lstControl.Hide();
                    txtControl.Focus();
                }
            };
        }

        private static string GetLastString(string s)
        {
            string[] strArray = s.Split(' ');
            return strArray[strArray.Length - 1];
        }
    }
}

Calling the Method

The TextBox KeyUp Event is suitable for calling the above method. The following code is needed to be entered in the TextBox KeyUp Event.

C#
txtInput.KeyUp += (s, e) => {
                List<string> DictionaryList = new List<string>(new string[] 
                { "AZEAL", "JOB", "INFO", "SOLUTIONS", 
                "CODE", "PROJECT", "FACEBOOK", "APPLE", 
                "MICROSOFT", "WINDOWS","SELECT","SET","COM"}.ToList());
                clsIntelliSense.AutoCompleteTextBox(txtInput, lstPopup, DictionaryList, e);
            }; 

Points of Interest

I figured this out while thinking about how Visual Studio's IntelliSense works.

History

This is preliminary. Later, we will think about the grammar & case sensitive listings to implement in this code.

Bug Fix: Listbox gets focus when pressing the up and down key on textbox while showing the listbox.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer Azeal Groups
India India
Thinking Innovation. .. ...

Technologies: .NET, Java, PHP, Python, SQL, Android, HTML, .

Comments and Discussions

 
QuestionAutomatic transfer of clicked word from listbox to textbox Pin
Member 138145776-May-18 20:07
Member 138145776-May-18 20:07 
Questiontwo word dictionary problem Pin
mahmuthaktan21-Dec-16 3:39
mahmuthaktan21-Dec-16 3:39 
QuestionA couple of suggested fixes Pin
Mikaelg24-Feb-16 12:36
Mikaelg24-Feb-16 12:36 
I like the basics of this and I will make use of it in a modified state.

There are issues however

1. You need to push up/down twice before the listbox reacts to input (first time you set focus, next time it reacts to your input)

2. When the listbox has focus you can no longer write in the textbox until you have either selected an item from the auto complete list or you have manually selected the textbox again with your mouse

3. The auto complete list is reloaded every key press. It should only be reloaded if the user changes the auto complete word, not if the user presses special buttons like up/down/left/right/esc etc.

4. As mentioned before the auto complete only works for the last word, it should be sensitive to your current location instead.

I did a couple of test changes to your code and basicly fixed 1-3 with very small changes.

1. I moved the code to load the auto complete list to a separate method
2. I changed it so that the method to load the auto complete list is called only if no special key have been pressed. (In my simple change the only special keys are up and down)
3. I removed the code that sets focus and replaced it with code that add or subtract to the selected index of the list control (if it is within the bounds of the control)

What I got from these changes is that the textbox always have focus, I can check the auto complete list out and select an item from it, or I can keep on writing in the textbox to narrow the alternatives down.

As I said in the beginning I will be using your code in a modified state Smile | :) Thank you!
AnswerRe: A couple of suggested fixes Pin
Member 118422041-Feb-17 23:11
Member 118422041-Feb-17 23:11 
QuestionModify it to make it work when text is inserted in the middle Pin
Amit Hegde6-Dec-14 10:53
Amit Hegde6-Dec-14 10:53 
GeneralMy vote of 5 Pin
Tom Marvolo Riddle15-Mar-14 1:28
professionalTom Marvolo Riddle15-Mar-14 1:28 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.