2011-04-15 79 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); 
     } 
    } 

} 
相關問題