2011-04-15 58 views
4

我有一个ObservableCollection我的基础项目列表。我有2 CollectionViewSource这是数据的不同过滤器。我想要发生在CollectionViewSource中的任何变化。更新CollectionViewViewSource当ObservableCollection更改WP7

在我的视图模型构造函数中,我设置了过滤器谓词。然后我得到数据并将其添加到ObservableCollection。我订阅了CollectionChanged活动,并在那里刷新CVS。

虽然我看到一些非常奇怪的东西。这些项目不会出现在绑定到CVS的我的ListBox中,否则会显示重复项。如果我在CollectionChanged事件之外的CVS上拨打Refresh后,我更改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(); 
} 

回答

3

CollectionViewSource没有实现INotifyPropertyChanged,因此要获得任何基础数据的变化到你需要调用Refresh上查看你已经做的UI。 CollectionViewSource也是数据源不可知的,所以源是ObservableCollection这一事实引发属性更改通知并不重要,因为CollectionViewSource未在侦听。

我认为在集合更改时手动刷新视图的解决方案最好是在不重新考虑数据结构的情况下获得的。

+0

我所看到的是把刷新`CollectionChanged`事件的问题。如果我在更改集合后调用“刷新”,则看不到问题。这是一个知道的问题,或者我可以做些什么来解决这个问题?我可以在从ObservableCollection中添加/删除某些东西后手动调用Refresh,但是我不明白为什么从`CollectionChanged`事件中调用它时不应该起作用。 – 2011-04-15 16:23:13

0

问题是ObservableCollection有其局限性。考虑一下你在代码中使用的循环,它可能叫做Add方法吗?因此,更改的事件触发多少次以及刷新方法被调用的频率如何?当代码快速连续发生如此多的变化时,这段代码就会陷入困境,这并不奇怪。

ObservableCollection是伟大的,当它开始加载,那么它的变化情况进行监控和小型相对较少的变化是从点进行。对于大规模更改,最好加载一个全新的实例,然后将这个新实例分配给一个属性。

让属性设置器重新指定CollectionViewSource对象的Source属性。如果你仍然想观察集合,你可以在setter中加入你的事件处理函数。

2

我知道这有点老了,但我使用特异性克服了上面(CollectionChangedEvent事件引发多次)中提到的限制修改的ObservableCollection类,发现here. (ObservableCollectionEx - blocks the CollectionChangedEvent until all are added by adding an AddRange method)

我已经使用了约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); 
     } 
    } 

} 
相关问题