Darth Sucuk
Darth Sucuk

Reputation: 254

How to search listview's items with textbox in c#

I have a listview name listView1 and it contains computer id's and their some infos.So what I want to do is I have a textbox name filterbox and when I write something it will filter it,it works fine.My problem is it just look for the first column not the others.For example ;

PCNAME  USER  MODEL
 AAAA   JOHN  DELL
 BBBB   MIKE  TOSHIBA
 CCCC   ASH   MONSTER

when I type BB it just gets the second row and it works fine but if I type DELL it gets me nothing.

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

Upvotes: 3

Views: 4947

Answers (3)

TheGeneral
TheGeneral

Reputation: 81493

It's as simple as iterating the sub items:

foreach (ListViewItem item in listView1.Items)
   foreach (ListViewItem.ListViewSubItem subitem in item.SubItems)
      if (subitem.Text.Equals(filterbox.Text, StringComparison.OrdinalIgnoreCase))
      {
         item.BackColor = SystemColors.Highlight;
         item.ForeColor = SystemColors.HighlightText;
         break;
      }

Note, you had other things going on here, however I'll leave them details up to you.

Update

For filtering you could use some Linq:

if (filterbox.Text == "")
{
   return;
}

var list = listView1.Items
                    .Cast<ListViewItem>()
                    .Where(
                        x => x.SubItems
                              .Cast<ListViewItem.ListViewSubItem>()
                              .Any(y => y.Text.Contains(filterbox.Text)))
                    .ToArray();
listView1.Items.Clear();
listView1.Items.AddRange(list);

Upvotes: 4

TaW
TaW

Reputation: 54433

The core of Saruman's answer works pretty well: Copy all items that fit the criteria into an enumerable collection with linq, clear the listview items and AddRange the good ones.

A few corrections are needed however for a fully working solution.

First: We need store the full set of items somewhere. Best in a class level variable:

List<ListViewItem> allItems = new List<ListViewItem>();

We need to fill it after the full set of items has been added:

allItems.Clear();
allItems.AddRange(listView1.Items.Cast<ListViewItem>());

Now we can code the TextChanged event of our filterTextbox; here we always use the full set of data:

private void filterbox_TextChanged(object sender, EventArgs e)
{
    listView1.Items.Clear();   // clear all items we have atm
    if (filterbox.Text == "")
    {
        listView1.Items.AddRange(allItems.ToArray());  // no filter: add all items
        return;
    }
    // now we find all items that have a suitable text in any subitem/field/column
    var list = allItems.Cast<ListViewItem>()
                       .Where( x => x.SubItems
                                     .Cast<ListViewItem.ListViewSubItem>()
                                     .Any(y => y.Text.Contains(filterbox.Text)))
                       .ToArray();
    listView1.Items.AddRange(list);  // now we add the result
}

Kudos to Saruman who wrote the linq with the necessary Casts!

Btw: We should and do use Cast instead of OfType because we can be sure of the types. Cast is a bit faster.

Upvotes: 4

Ketan
Ketan

Reputation: 89

You can bind your list-view with data table. refer bind list-view with data-table . And on text-box "text changed/control leave" event apply filter on data-table. This will take care of updating items of the list-view as it's data source is bound to data-table.

listView1.ItemsSource = dataTable.DefaultView;

Filter data using below query.

DataView dv = new DataView(yourDatatable);
dv.RowFilter = "query"; // query example = "id = 10"

Let me know if it helps. :)

Upvotes: 2

Related Questions