0

My code goes as follows. And it works perfectly fine:

    private void frmSearch_Load(object sender, EventArgs e)
    {
        //Get DB records for textBox search
        dt = Talika.PanktiLa("select * from VM"); //note - dt is a datatable. Talika.Panktila is a class I have created for retrieving records from the database. If you need the code to answer this question, let me know and I will post it here

        //Enable AutoComplete for textBox
        //Do this only if Vendor Master has records
        if (dt.Rows.Count != 0)
        {                
            //Create the list to be used as custom source.
            var source = new AutoCompleteStringCollection();
            foreach (DataRow dr in dt.Rows)
                source.Add(dr["VNAME"].ToString());

            //Bind to textBox.
            txtSearch.AutoCompleteCustomSource = source;
            txtSearch.AutoCompleteMode = AutoCompleteMode.Suggest;
            txtSearch.AutoCompleteSource = AutoCompleteSource.CustomSource;
        }
    }

Now, I want to add some advanced search functionality.

Eg. If I want to search for "Apple Computer Inc"
It should appear when I type:
"Computer" or a part of it
or "Inc"
or "ACI" (initials of the name)

Can I add this functionality to the existing AutoComplete code, or will I have to do away with it and code for it from scratch?

Prasad Kamath
  • 182
  • 2
  • 15
  • Side note. Don't fetch the entire table just to use one column. Only fetch what you need: `dt = Talika.PanktiLa("select VNAME from VM")`. – Racil Hilan Apr 14 '18 at 19:13
  • [Try this:](https://stackoverflow.com/a/800407/7738489) Here you can get reference for Autocomplete textbox – Dinkar Veer Apr 15 '18 at 04:00
  • @RacilHilan - I use the same `DataTable` for further processing. Hence I need to fetch the entire table. – Prasad Kamath Apr 26 '18 at 18:33

2 Answers2

1

I could not get satisfactory code from any of the samples, hence I designed my own. Below is the code. It works perfectly. The only thing it doesn't do is search by initials, which is fine for now. It needs a textbox, listbox and a button to work. Hope someone gets benefited by it.

namespace MM
{
public partial class frmSearch : Form
{
    DataTable dt = new DataTable();
    DataRow[] passrow = new DataRow[1]; //to hold a particular row of datagridview
    bool jod = true; //True - add new record, false - edit record

    public frmSearch()
    {
        InitializeComponent();
    }

    private void frmSearch_Load(object sender, EventArgs e)
    {

    }

    private void txtSearch_Enter(object sender, EventArgs e)
    {
        //Get DB records for textBox search
        dt = Talika.PanktiLa("select * from VM");
    }

    private void txtSearch_MouseHover(object sender, EventArgs e)
    {
        toolTip1.Show("Press Enter to search", txtSearch);
    }

    private void txtSearch_KeyDown(object sender, KeyEventArgs e)
    {
        //If ENTER is pressed
        //Go to ADD NEW button if textBox is empty
        //Load Vendor Master form if text is present
        if (e.KeyCode == Keys.Return)
            if (txtSearch.Text == String.Empty)
                this.SelectNextControl(ActiveControl, true, true, true, true);
            else
                Load_Vendor_Master();

        //If DOWN ARROW is pressed
        //Focus on listbox if textBox has text
        //Focus on ADD NEW button if textBox is blank
        if (e.KeyCode == Keys.Down)
        {
            if (txtSearch.Text != String.Empty)
            {
                this.SelectNextControl(ActiveControl, true, true, true, true);
                lstSearch.SelectedIndex = 0;
            }
            else if (txtSearch.Text == String.Empty)
                this.SelectNextControl(ActiveControl, true, true, true, true);
        }

        //If ESC is pressed
        //Clear contents of textBox
        if (e.KeyCode == Keys.Escape)
            txtSearch.Text = String.Empty;

        //If RIGHT ARROW is pressed
        //Go to ADD NEW button
        if (e.KeyCode == Keys.Right)
            this.SelectNextControl(ActiveControl, true, true, true, true);
    }

    private void txtSearch_TextChanged(object sender, EventArgs e)
    {
        //Hide listbox if textbox is empty
        if (txtSearch.Text == String.Empty)
        {
            lstSearch.Hide();
            return;
        }

        //Proceed only if Vendor Master has records
        if (dt.Rows.Count != 0)
        {
            //Clear listbox so that new results can be populated.
            lstSearch.Items.Clear();

            //Populate listbox based on search results.
            foreach (DataRow dr in dt.Rows)
            {
                //Have to convert to upper case, else search doesnt work effectively.
                string s = dr["VNAME"].ToString().ToUpper();

                //Populate listBox.
                if (s.Contains(txtSearch.Text.ToUpper()))
                    lstSearch.Items.Add(s);
            }

            //Show listBox
            lstSearch.Visible = true;
        }
    }

    private void txtSearch_KeyUp(object sender, KeyEventArgs e)
    {

    }

    private void lstSearch_KeyDown(object sender, KeyEventArgs e)
    {
        //If ENTER is pressed
        //Populate textBox with listBox item
        //Put focus back on textBox
        if (e.KeyCode == Keys.Enter)
        {
            //Populate textBox with selected item
            txtSearch.Text = lstSearch.SelectedItem.ToString();

            //Put focus on textBox
            this.SelectNextControl(ActiveControl, false, true, true, true);

            //Hide listBox
            lstSearch.Visible = false;

            //Load Vendor Master form
            Load_Vendor_Master();
        }

        //If cursor in on the first item of listBox
        //And UP ARROW is pressed
        //Highlight the textbox
        if (lstSearch.SelectedIndex == 0)
            if (e.KeyCode == Keys.Up)
                this.SelectNextControl(ActiveControl, false, true, true, true);

        //If BACKSPACE is pressed
        //Delete last character of textBox
        //Set focus on textBox
        if (e.KeyCode == Keys.Back)
        {
            //Do this only if textbox is not empty
            if (txtSearch.Text != String.Empty)
            {
                //Delete last char
                txtSearch.Text = txtSearch.Text.Substring(0, txtSearch.Text.Length - 1);

                //Set focus on textBox
                this.SelectNextControl(ActiveControl, false, true, true, true);

                //Set cursor at end of text
                txtSearch.SelectionStart = txtSearch.TextLength;
            }
        }

        //If ESC is pressed
        //Hide listBox
        //Clear textBox contents
        //Set focus on textBox
        if (e.KeyCode == Keys.Escape)
        {
            lstSearch.Visible = false;
            txtSearch.Text = String.Empty;
            this.SelectNextControl(ActiveControl, false, true, true, true);
        }

        //If letter or digit is pressed
        //Type the char at the end of the text
        //Set focus on textBox
        bool isLetterOrDigit = char.IsLetterOrDigit((char) e.KeyCode);
        if (isLetterOrDigit ==  true)
        {
            //Add the char to text
            txtSearch.Text += (char)e.KeyCode;

            //Set cursor at end of text
            txtSearch.SelectionStart = txtSearch.TextLength;

            //Set focus on textBox
            this.SelectNextControl(ActiveControl, false, true, true, true);
        }
    }

    private void Load_Vendor_Master()
    {
        //Hide listbox
        lstSearch.Visible = false;

        //Read dt for matching records
        /* Replace("'", "''") helps to match names containing apostrophe.
        Single apostrophe is a string delimiter, 
        hence it is replaced with two single apostrophes which is interpreted as a single apostrophe */
        passrow = dt.Select("VNAME = '" + txtSearch.Text.Replace("'", "''") + "'");

        //Set flag
        jod = false; //Edit record

        //Load vendor master form
        //Do this only if datarow has rows (in this case, a single row)
        if (passrow.Length != 0)
        {
            frmVM frmVM_edit = new frmVM(passrow[0], jod);
            frmVM_edit.ShowDialog();

            //Get updated DB records for textBox search
            dt.Clear();
            txtSearch_Enter(null, null);
        }
    }

    private void btnAdd_Click(object sender, EventArgs e)
    {
        //Set flag
        jod = true; //Add new record

        //Load form
        frmVM frmVM_add = new frmVM(null, jod);
        frmVM_add.ShowDialog();
        this.Close();
    }

    private void frmSearch_KeyDown(object sender, KeyEventArgs e)
    {
        //Close form when ESC key is pressed
        //Do this only if textBox is blank
        //Because ESC is also used to clear textBox
        if (e.KeyCode == Keys.Escape)
            if (txtSearch.Text == String.Empty)
                this.Close();
    }

    private void lstSearch_SelectedIndexChanged(object sender, EventArgs e)
    {

    }

    private void btnAdd_KeyDown(object sender, KeyEventArgs e)
    {
        //If RIGHT or LEFT arrow is pressed
        //Go to textBox
        if (e.KeyCode == Keys.Right || e.KeyCode == Keys.Left)
            this.SelectNextControl(ActiveControl, false, true, true, true);
    }
}

public static class Talika //This is declared in one form and can be accessed from any form in the entire solution without declaring it again
{
    public static DataTable PanktiLa(string queryLe)
    {
        try
        {
            string connString = System.IO.File.ReadAllText(Application.StartupPath + "\\MM.ini") + " User ID = sa; Password = DEMO";
            DataTable dt_local = new DataTable();

            using (SqlConnection conn = new SqlConnection(connString))
            {
                SqlCommand cmd = new SqlCommand(queryLe, conn);
                SqlDataAdapter adapter = new SqlDataAdapter();

                conn.Open();
                adapter.SelectCommand = cmd;

                adapter.Fill(dt_local);
                return (dt_local);
            }
        }
        catch (Exception ex)
        {
            MessageBox.Show("Please contact the program vendor with this error code:\n\n" + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            return (null);
        }
    }
}
}
Prasad Kamath
  • 182
  • 2
  • 15
0

pass ACO_NOPREFIXFILTERING to IAutoComplete2.SetOptions to disable prefix filtering. WinForms has no extension point to let you access the underline COM API, so you need to disable the Winforms autocomplete and hookup your own autocomplete object with IAutoComplete::Init. WinForms's implementation of IEnumString for this purpose is not public, you need to write your own.

In the TextChanged event of your textbox, change your candidate list based on the current content of the text box. Then call IAutoCompleteDropDown::ResetEnumerator to update the dropdown.

Sheng Jiang 蒋晟
  • 15,125
  • 2
  • 28
  • 46