当ObservableCollection发生变化时更新CollectionViewSource WP7

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了当ObservableCollection发生变化时更新CollectionViewSource WP7相关的知识,希望对你有一定的参考价值。

我有一个ObservableCollection 为我的基础项目列表。我有两个 CollectionViewSource 是数据的不同过滤器。我希望任何发生的变化都能反映在数据的 CollectionViewSource.

在我的视图模型构造函数中,我设置了过滤谓词。然后我获取数据并将其添加到 ObservableCollection. 我已经订阅了 CollectionChanged 事件,并在那里刷新CVS。

但我看到一些非常奇怪的事情。要么这些项目不显示在我的 ListBox 绑定到CVS的,否则会出现重复。如果我调用 Refresh 在中央统计局之外的 CollectionChanged 事件后,我改变了 ObservableCollection我觉得一切都很好,我很想在集合发生变化的时候,能够直接刷新,而不用担心每次做了什么改变后,都要调用刷新。我真的很希望能够在集合发生变化时直接刷新,而不用担心每次做了改变集合的事情后都要调用刷新。

public MyViewModel()
{
    oc.CollectionChanged += OcCollectionChanged;

    cvs1.Source = oc;
    cvs1.View.Filter = new Predicate<object>( ... );

    cvs2.Source = oc;
    cvs2.View.Filter = new Predicate<object>( ... );

    foreach( var data in myData )
    {
        oc.Add( data );
    }
}

private void OcCollectionChanged( object sender, NotifyCollectionChangedEventArgs e )
{
    cvs1.View.Refresh();
    cvs2.View.Refresh();
}
答案

CollectionViewSource 没有实现 INotifyPropertyChanged因此,要想将任何底层数据的变化传递到UI中,你需要调用 Refresh 就像你已经在做的那样。CollectionViewSource 也是数据源不可知的,所以事实上,源是个 ObservableCollection 引起属性变更通知的是不重要的,因为 CollectionViewSource 是不听的。

我认为,当集合发生变化时,手动刷新视图是最好的解决方案,而不需要重新思考你的数据结构。

另一答案

我使用的是一个修改过的 ObservableCollection 类,特别是克服上述限制的类(CollectionChangedEvent 事件多次发生),发现 这里。(ObservableCollectionEx - 阻止CollectionChangedEvent,直到通过添加一个AddRange方法将所有的人都添加进来)

我已经使用它2年了,它对于大的集合变化非常好用。

更新: 看来那个链接已经关闭了,所以这里是代码。

public class ObservableCollectionEx<T> : ObservableCollection<T>
{
    public ObservableCollectionEx()
        : base()
    {
        _suspendCollectionChangeNotification = false;
    }


    bool _suspendCollectionChangeNotification;

    protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
    {
        if(!_suspendCollectionChangeNotification)
        {
            base.OnCollectionChanged(e);
        }
    }

    public void SuspendCollectionChangeNotification()
    {
        _suspendCollectionChangeNotification = true;
    }

    public void ResumeCollectionChangeNotification()
    {
        _suspendCollectionChangeNotification = false;
    }


    public void AddRange(IEnumerable<T> items)
    {
        this.SuspendCollectionChangeNotification();
        int index = base.Count;
        try
        {
            foreach(var i in items)
            {
                base.InsertItem(base.Count, i);
            }
        }
        finally
        {
            this.ResumeCollectionChangeNotification();
            var arg = new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset);
            this.OnCollectionChanged(arg);
        }
    }

}
另一答案

问题是... ObservableCollection 有其局限性。 考虑一下你的代码中的那个循环,它调用了多少次的 Add 方法? 因此,改变了的事件会被触发多少次,刷新方法会被调用多少次? 当如此多的变化连续发生时,这段代码陷入困境也就不足为奇了。

ObservableCollection 是很好的,当它最初被加载时,它的变化事件就会被监控,然后从这一点上进行相对不频繁的小变化。 对于大规模的变化,最好是加载一个全新的实例,然后将这个新实例分配给一个属性。

让属性设置者重新分配 Source 上的属性 CollectionViewSource 对象。 如果你还想观察这个集合,你也可以在setter中分离并附加你的事件处理程序。

以上是关于当ObservableCollection发生变化时更新CollectionViewSource WP7的主要内容,如果未能解决你的问题,请参考以下文章

wpf中,当DataGrid.ItemsSource与ObservableCollection绑定后,值变化时,DataGrid如何刷新?

ObservableCollection 与list

wpf画面ListBox绑定的数据发生变化时 画面闪烁

当 Item 改变时通知 ObservableCollection

强制数据绑定 WPF ListBox 更新的更好方法?

当实际数据发生变化时,结果缓存数据会发生啥变化?