因為最近在WPF專案中,遇到ObservableCollection這個屬性的頻繁使用,一個一個坑跳過來,今天看到這個貼子
玩轉INotifyPropertyChanged和ObservableCollection - 包建強 - 部落格園 (cnblogs.com)
其中分析很透徹了,但是留了一點遺憾,而且在其中引起了一個想法,做一個專案來測試一下。
我們知道在Binding一個item的時候,想要其中屬性變化時,UI同步變化,需要實現OnPropertyChanged介面,我因為習慣於mvvm.Toolkit,也就是說需要繼承ObservableObject,
類似這樣:
public class Student:ObservableObject { private string name; public string Name { get => name; set => SetProperty(ref name, value); } private int age; public int Age { get => age; set=>SetProperty(ref age, value); } }
在Binding到集合項的時候,通常需要這樣
pulic ObservableCollection<Student> Students_t = new ();
透過上面2條,可以實現:集合中增加、刪除元素,及元素屬性更新的時候,UI可自動更新。
但是,但是的但是,如果需要重新整理資料的時候,比如說,人工清除當前集合,重新從源頭讀取,通常這樣:
Students=new ObservableCollection<Student>(ctx.students)
這就壞了,發現UI沒更新。原因在於,ObservableCollection只關注內部的元素變化,但當他自己發生了變化,其實對集合Binding關係已經破壞了,因為這是一個新建的集合,等於更新了Students這個物件,而不是對這個物件的內部元素作出的增刪。
希望我說得明白了。
如果我說明白了,就是說,前面我們忽略了一個問題。
Students仍然不是可觀察物件。
所以,要修改為
private ObservableCollection<Student> students_c = new (); public ObservableCollection<Student> Student_c { get => students_c; set => SetProperty(ref students_c, value); }
}
開始我說的忽發奇想是,如果我對List<T>實現可觀察,是否能夠代替了ObservableCollection?測試結果是,是的,在重置資料的時候,確實是可以實現的(很奇怪嗎?),但是在增刪元素的時候,仍然不行,仍然需要ObservableCollection。
對以上各種情況,我做的測試專案,見:
https://gitee.com/ppcba/observable-collection-demo.git
如果有同樣疑惑的,建議參考著自己做一下,不然會仍然糊塗著。
==========2023-5-7補充=========
ObservableCollection的重置還有一種場景,就是自身不帶AddRange方法,只好更新它後面的資料來源,習慣上是這樣使用的:
StuList.AddRange(stus);
Students=New ObservableCollection<Student>(StuList);
這就使得ObservableCollection被重置了。
所以,我現在專案上,仍然把ObservableCollection作為欄位,而不是屬性,需要重置的時候,就清空,然後使用擴充套件方法AddRange方法。
但從MVVM強迫症的角度,還是一切OnPropertyChanged進行到底為好。