Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Search listview items using textbox

I am working on a simple application (phonebook) in C# and in my project I have got a listview filled with contacts. I have been trying to implement the possibility to automatically (instantly) search through a listview using a textbox. I have managed to make it work, but not in the desired way. You will realise the actual problem if I give you an example. Let's say that I have got a contact named Bill Gates and when I try searching for it - it gets found and that part is OK. But, the problem is when I try to search for another contact. In that case, I have to clear the textbox before I type another name, but it is possible to remove only letter by letter. When I start removing the whole name, after removing a first letter it acts like I have just entered the name - it selects the item (and focuses as well) - actually there is no time to remove the whole name before it finds a contact again. I have to remove a first letter, then switch back to the textbox, remove another letter etc. Is there any solution for searching to be automatic - as it is now, but on the other hand for removing (clearing the textbox) without selecting contacts to be possible.

Take a look at the code:

private void txt_Search_TextChanged(object sender, System.EventArgs e)
    {
        if (txt_Search.Text != "")
        {
            foreach (ListViewItem item in listView1.Items)
            {
                if (item.Text.ToLower().Contains(txt_Search.Text.ToLower()))
                {
                    item.Selected = true;
                }
                else
                {
                    listView1.Items.Remove(item);
                }

            }
            if (listView1.SelectedItems.Count == 1)
            {
                listView1.Focus();
            }
        }
        else 
        { 
            LoadContacts();
            RefreshAll();
        }
    } 
like image 287
Exinta Enea Avatar asked Feb 14 '23 12:02

Exinta Enea


2 Answers

There are some things wrong in your code, firstly when modifying a collection in a loop through it, we should not use foreach although in some case it seems to work but not really, it will surely be strange in future and confuse you. We should use a for loop instead and loop in the reverse order. The second wrong thing is you set the Selected to true which may cause your textBox lose focus to the listView. The solution is we have to use some other way to indicate that the item is selected, such as by using BackColor instead:

private void txt_Search_TextChanged(object sender, System.EventArgs e)
{
    if (txt_Search.Text != "") {
        for(int i = listView1.Items.Count - 1; i >= 0; i--) {
            var item = listView1.Items[i];
            if (item.Text.ToLower().Contains(txt_Search.Text.ToLower())) {
                item.BackColor = SystemColors.Highlight;
                item.ForeColor = SystemColors.HighlightText;
            }
            else {
                listView1.Items.Remove(item);
            }
        }
        if (listView1.SelectedItems.Count == 1) {
            listView1.Focus();
        }
    }
    else   
        LoadContacts();
        RefreshAll();
    }
}

Also after user focusing the ListView, all the BackColor and ForeColor should be reset, we can handle the Enter event of ListView:

//Enter event handler for listView1
private void listView1_Enter(object sender, EventArgs e){
  foreach(ListViewItem item in listView1.Items){
    item.BackColor = SystemColors.Window;
    item.ForeColor = SystemColors.WindowText;
  }
}
like image 99
King King Avatar answered Feb 24 '23 05:02

King King


EDIT you better not use Text_Changed, rather try Key_Down method as follows

private void txt_Search_KeyDown(object sender, KeyEventArgs e)
{
   if (e.KeyCode == Keys.Enter) //apply your search only when pressing ENTER key
     {
       // you do your search as it was before 
       // i personally don't have suggestions here
       if (!txt_Search.AutoCompleteCustomSource.Contains(txt_Search.Text)) txt_Search.AutoCompleteCustomSource.Add(txt_Search.Text);
       //the line above will save all your searched contacts and display it in a beautiful format
     }
   else if (txt_Search.Text == "")
     {
       LoadContacts();
       RefreshAll();
     }
}

Of course don't forget to set the properties of txt_Search AutoCompleteMode = SuggestAppend and AutoCompleteSource = CustomSource

like image 27
chouaib Avatar answered Feb 24 '23 04:02

chouaib