Фильтрация ObservableCollection? - PullRequest
12 голосов
/ 25 апреля 2011

Когда я связываю ListBox непосредственно с ObservableCollection, я получаю обновления в реальном времени, отображаемые в моем ListBox, но как только я добавляю другие методы LINQ в смесь, мой 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());
    }
}

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

Однако, если я перейду с

        listBox1.ItemsSource = Words;

до

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

ListBox больше не обновляется.

Как я могу добавить «фильтр» между моей ObservableCollection и ListBox, и при этом заставить его обновляться без необходимости заново устанавливать .ItemsSource?

Ответы [ 3 ]

21 голосов
/ 26 апреля 2011

Попробуйте использовать 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(":");
}
6 голосов
/ 26 апреля 2011

Почему не работает:

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

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

3 голосов
/ 25 апреля 2011

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

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

...


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