Фильтрация коллекции ObservableCollection?

когда я привязываю ListBox непосредственно к ObservableCollection, я получаю обновления в реальном времени, отображаемые в моем ListBox, но как только я добавляю другие методы LINQ в mix, мой ListBox больше не уведомляется о каких-либо изменениях в ObservableCollection.

вот, позвольте мне проиллюстрировать на примере;

public partial class MainPage : PhoneApplicationPage
{
    ObservableCollection<String> Words = new ObservableCollection<string>();

    public MainPage()
    {
        InitializeComponent();
        listBox1.ItemsSource = Words;
    }

    private void AddButton_Click(object sender, RoutedEventArgs e)
    {
        Words.Add(DateTime.Now.ToString());
    }
}

здесь я добавил кнопку и список на простую страницу, и нажатие кнопки заставляет новый элемент немедленно появляться в списке.

, если я изменюсь с
        listBox1.ItemsSource = Words;

to

        listBox1.ItemsSource = Words.Where(w => w.Contains(":"));

список больше не обновляется.

как я могу добавить "фильтр" между моей ObservableCollection и ListBox, и все еще получить его для обновления без необходимости устанавливать .Опять же, что ItemsSource?

3 ответов


попробуйте использовать CollectionViewSource следующим образом:

WordsView = new CollectionViewSource();
WordsView.Filter += Words_Filter;
WordsView.Source = Words;

// ...
void Words_Filter(object sender, FilterEventArgs e)
{
    if (e.Item != null)
        e.Accepted = ((string)e.Item).Contains(":");
}

почему это не работает:

listBox1.ItemsSource = Words.Where(w => w.Contains(":"));

вы не связываете ObservableCollection, но IEnumerable, созданный Linq. Этот новый "список" не уведомляет ListBox об изменениях в списке.


вы должны использовать ICollectionView.Filter свойства:

ICollectionView view = CollectionViewSource.GetDefaultView(Words);
view.Filter = WordFilter;

...


bool WordFilter(object o)
{
    string w = (string)o;
    return w.Contains(":")
}