2010-11-29 39 views
8

當使用WPF數據綁定時,我顯然無法沿着MyCollection = new CollectionType<Whatever>(WhateverQuery());的方向行事,因爲綁定引用了舊集合。我的解決方法到目前爲止是MyCollection.Clear();後跟foreach MyCollection.Add(item); - 這是非常糟糕的性能和美觀。WPF:沒有清除/添加替換數據綁定收集內容

ICollectionView,雖然很整潔,但也不能解決問題,因爲它是SourceCollection屬性是隻讀的;無賴,因爲這將是一個不錯的和簡單的解決方案。

其他人是如何處理這個問題的?應該提及的是,我在做MVVM,因此不能通過單個控件綁定進行搜索。我想我可以製作一個圍繞ObservableCollection的包裝,其中包含一個ReplaceSourceCollection()方法,但在走這條路線之前,我想知道是否還有其他一些最佳做法。

編輯:

有關的WinForms,我會綁定控件針對BindingSource,讓我簡單地更新它的DataSource屬性和調用ResetBindings()方法 - 急,底層集合有效改變。我希望WPF數據綁定可以支持類似的場景嗎?示例(僞代碼)代碼:WPF控件(ListBox,DataGrid,不管您喜歡)綁定到Users屬性。我認識到,集合應該是隻讀的,以避免ReloadUsersBad()表現出的問題,但後來這個例子中,糟糕的代碼顯然不會編譯:)

public class UserEditorViewModel 
{ 
    public ObservableCollection<UserViewModel> Users { get; set; } 

    public IEnumerable<UserViewModel> LoadUsersFromWhateverSource() { /* ... */ } 

    public void ReloadUsersBad() 
    { 
     // bad: the collection is updated, but the WPF control is bound to the old reference. 
     Users = new ObservableCollection<User>(LoadUsersFromWhateverSource()); 
    } 

    public void ReloadUsersWorksButIsInefficient() 
    { 
     // works: collection object is kept, and items are replaced; inefficient, though. 
     Users.Clear(); 
     foreach(var user in LoadUsersFromWhateverSource()) 
      Users.Add(user); 
    } 

    // ...whatever other stuff. 
} 
+0

你可以請張貼一些代碼? – TalentTuner 2010-11-29 10:49:20

+0

+1好問題。我有一段時間沒有在WPF中做過任何事情,但另一種不同語言的框架具有相似的概念,並通過停止運行循環,更改大量屬性,然後解除運行循環來解決此問題。我正在尋找類似的東西。 – 2010-11-29 11:12:28

回答

4

如果對象MyCollection是實現INotifyPropertyChanged,您可以簡單地替換集合。

一個例子:

public class MyClass : INotifyPropertyChanged 
{ 
    public event PropertyChangedEventHandler PropertyChanged; 
    private ObservableCollection<Whatever> _myCollection; 

    private void NotifyChanged(string property) 
    { 
     if (PropertyChanged != null) 
      PropertyChanged(this, new PropertyChangedEventArgs(property)); 
    } 

    public ObservableCollection<Whatever> MyCollection 
    { 
     get 
     { 
      return _myCollection; 
     } 
     set 
     { 
      if (!ReferenceEquals(_myCollection, value)) 
      { 
       _myCollection = value; 
       NotifyChanged("MyCollection"); 
      } 
     } 
    } 
} 

有了這個,當你指定一個集合,WPF檢測這一切都得到更新。

這是我如何解決這個問題。

1

下面的鏈接解釋如何實現的AddRange方法。

http://blogs.msdn.com/b/nathannesbit/archive/2009/04/20/addrange-and-observablecollection.aspx

它看起來像你堅持實現一個子類,正確處理這種情況。

顯然,某些控件不支持批量收集更改通知。至少他們沒有寫這篇文章的時候。雖然現在你應該有更多的信息,如果你想進一步調查。

+0

體面處理批處理更新的文章(與完全替換相反) - 討厭ListCollectionView只支持單項更新: – snemarch 2010-11-29 11:37:11