'show/ hide items in the listbox

I make a listbox and it works perfectly, I also made a search function, but I want to hide the items in the listbox and show them only when searched through index. here is my code for adding items

private void Savebtn_Click(object sender, EventArgs e)
{
    addTolist(gatherItem());
    refreshView();
}

private void addTolist(Person p)
{
    Person.listperson.Add(p);
}

private void refreshView()
{
    listBox1.Items.Add(getItem());
}

private String getItem()
{
    String result = null;
    foreach (Person p in Person.listperson)
    {
        result = p.lastname;
    }
    return result;
}

and this is my code for search

private void button1_Click(object sender, EventArgs e)
{
    int index = listBox1.FindString(textBox6.Text);
    if (0 <= index)
    {
        listBox1.SelectedIndex = index;
    }
}

Is there a way for this? thanks :)



Solution 1:[1]

There is no easy way to do this with winforms. It a lot easier with WPF. With winforms you will have to remove the items. You could technically use databinding, but its not recommended at all, because listbox is supposed to used directly from your code according the MSDN documentation.

On second thought, you could overdraw the listbox and set the item you want to hide to transparent or something, buts its not easy. You may want to consider storing all your values in an array and then loop through array and only adding the elements you want. Or switch to WPF.

Hope this helps.

Solution 2:[2]

You can cover a dummy ListBox on your origin one, and set origin one invisible. Then you can archive the same effect by writing codes like

class DummyItem {
        public string text;
        public int index;
        public override string ToString() {
        return text;
    }
}

public void build_dummy() {
    listbox_dummy.Items.Clear();

    for (int i = 0; i < listbox_origin.Items.Count; i++) {

        // replace with your own judgement
        if (! should_hide(listbox_origin.Items[i])) {
            DummyItem item = new DummyItem();
            item.text = listbox_origin.Items[i].ToString();
            item.index = i;
            listbox_dummy.Items.Add(item);
        }

    }
}

private void listbox_dummy_SelectedIndexChanged(object sender, EventArgs e) {
    var item = (DummyItem) listbox_dummy.SelectedItem;
    var index = item.index;
    listbox_origin.SelectedIndex = index;
}

Solution 3:[3]

The easiest way to do this, is to create a List<string> item that will store removed items (or items that do not match the search-phrase given in textbox1), an int variable that will store how many characters there were the last time the TextChanged event was triggered, and then create a function for your listbox element that activates when the phrase in a textbox is updated:

private void textbox1_TextChanged(object sender, EventArgs e) {}

in this function, there are two things that could happen:

  • if a character was added to textbox1:

    • you iterate over the elements in your listbox.
    • remove the ones that do not contain the phrase in textbox1
  • if a character was removed from textbox1:

    • look through the List<string> variable you made to store the values you removed from your listbox
    • add back each item that fits the text in textbox1 (check for duplicates though)

Here's the code I wrote to use as reference:

private List<string> temporarilyRemovedSongs = new List<string>();
private int previousTextLength = 0;
private void filter_songs_textbox_TextChanged(object sender, EventArgs e)
{
    List<string> toRemove = new List<string>();
    string text = Tools.Strip(this.filter_songs_textbox.Text.ToLower());

    if (text.Length > this.previousTextLength)
    {
        // a char was added, remove songs that do not start with the search-phrase
        foreach (string song in this.songs_list.Items)
        {
            if (!song.ToLower().Contains(text))
            {
                this.temporarilyRemovedSongs.Add(song);
                toRemove.Add(song);
            }
        }

        foreach (string song in toRemove)
        {
            this.songs_list.Items.Remove(song);
        }
    }
    else
    {
        // a char was removed; look through removed songs to add back
        foreach (string song in this.temporarilyRemovedSongs)
        {
            if (song.Contains(text) && !this.songs_list.Items.Contains(song))
                this.songs_list.Items.Add(song);
        }
    }
    previousTextLength = text.Length;
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 FrostyFire
Solution 2 march1993
Solution 3 zChris128