过滤ObservableCollection?

13

当我将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());
    }
}

在这里,我将一个按钮和一个列表框添加到一个简单的页面中,点击按钮会使新的项目立即出现在列表框中。
然而,如果我从...
        listBox1.ItemsSource = Words;

to

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

ListBox 不再更新。

我如何在 ObservableCollection 和 ListBox 之间添加“过滤器”,并仍然使其在不必设置 .ItemsSource 的情况下更新?

3个回答

22

尝试使用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(":");
}

关于 ListBox 和 CollectionViewSource 之间的绑定怎么样?我以前不能像以前一样使用 .ItemsSource。我必须使用 .DataContext 吗? - Frode Lillerud
当然可以,只需将ItemsSource设置为WordsView.View属性即可。 - bendewey
@bendewey 这个解决方案还可以,但是仍然非常慢。 - onmyway133

6
为什么它不工作:
listBox1.ItemsSource = Words.Where(w => w.Contains(":"));

你没有将ObservableCollection绑定到Linq生成的IEnumerable上。这个新的“列表”不会向ListBox通知列表中的更改。

3
您应该使用 ICollectionView.Filter 属性:
ICollectionView view = CollectionViewSource.GetDefaultView(Words);
view.Filter = WordFilter;

...


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

它也支持Windows Phone 7吗?我在静态CollectionViewSource类中找不到GetDefaultView方法。 - Frode Lillerud
@Frode,显然不是这样的...这在WPF中可以工作;我检查了CollectionViewSource是否存在于Silverlight中,但我没有想到检查GetDefaultView...另一个选项是在XAML中显式创建CollectionViewSource,将其绑定到您的集合,并处理Filter事件。 - Thomas Levesque

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接