views:

489

answers:

1

Hi,

First the code (sorry if its not 100%) I am no expert and then the question follows.

    public partial class Window1 : Window
    {
    CollectionView cv;

    public Window1()
    {
        InitializeComponent();

        List<Person> ppl = new List<Person>();
        BitmapImage b = new BitmapImage(new Uri(@"http://i.stackoverflow.com/Content/Img/stackoverflow-logo-250.png",UriKind.Absolute));
        ppl.Add(new Person(b, "world1"));
        ppl.Add(new Person(b, "world2"));
        ppl.Add(new Person(b, "world3"));
        ppl.Add(new Person(b, "world4"));
        ppl.Add(new Person(b, "world5"));
        ppl.Add(new Person(b, "world6"));

        lb.ItemsSource = ppl;
        lb.SelectedIndex = 1;

        cv = (CollectionView)CollectionViewSource.GetDefaultView(lb.ItemsSource);

        new TextSearchFilter(cv, textBox1);
    }
}

public class TextSearchFilter
{
    public TextSearchFilter(CollectionView cv, TextBox tb)
    {
        string filterText = "";

        cv.Filter = delegate(object obj)
        {
            Person p = obj as Person;
            int index = p.Info.IndexOf(filterText,0,StringComparison.InvariantCultureIgnoreCase);
            return index > -1;
        };

        tb.TextChanged += delegate
        {
            filterText = tb.Text;
            cv.Refresh();
        };
    }
}

    class Person
    {
        private BitmapImage myImage;
        private string myInfo = "";

        public BitmapImage Image
        {
            get { return myImage; }
            set { myImage = value; }
        }

        public string Info
        {
            get { return myInfo; }
            set { myInfo = value; }
        }

        public Person(BitmapImage Image, string Info)
        {
            this.Image = Image;
            this.Info = Info;
        }
    }

Thank you for reading so far, as you would have understood by now is that the code filters a listbox based on the input in the textbox, which works like a charm btw.

My problem is how do I preserve the selection during filtering. When the window loads, the listbox has all the items in it and I select the first item, then I type something in the textbox and the listbox filters to only show the relevant items, after selecting another item I remove all the text from the text box which brings it back to the original state but this time the selection has changed to only the item that I selected in the filtered view (so instead of two items being shown as selected only one shows as selected). This behaviour is obvious as I am filtering on a collection, so the moment the collection changes the selection is lost.

Is there a way to preserve the selection? any pointers?

Many Thanks.

+1  A: 

Probably in your TextChanged event handler, you should store the ListBox's selected items, like so:

Person[] selectedPeople = new Person[lb.SelectedItems.Count];
lb.SelectedItems.CopyTo(selectedPeople, 0);

Then after refreshing the filter, add them back using:

foreach (Person p in selectedPeople)
{
    if(lb.Items.Contains(p))
    {
        lb.SelectedItems.Add(p);
    }
}

The reason I have it using CopyTo and saving in an array instead of just using:

IList selectedPeople = lb.SelectedItems;

is that the latter will just keep a reference to lb.SelectedItems, and the foreach would modify the enumeration, causing an exception to be thrown. There may be an easier way, but this should get you headed in the right direction.

Chris Doggett