2012-04-05 38 views
2

我們有一個WPF應用程序,比方說我有一個Department對象,在這我有課的一個ObservableCollection,每門課程裏面我有教師的一個ObservableCollection,每個老師裏面我有學生的一個ObservableCollection:如何檢測WPF中父對象的子項更改?

Department.cs ----的ObservableCollection課程

Course.cs ----的ObservableCollection教師

Teacher.cs ----的ObservableCollection學生

Student.cs ----姓名,年齡等

這4類都實現INotifyPropertyChanged的,他們正在通過自己很好,我想要實現的是無論何時處對象圖中的任何改變,無論是是一個學生的年齡得到改變,或者一個新的課程或一個老師被刪除,任何事情都是我想知道的,理想情況是通過一個像DepartmentChanged這樣的活動(理想情況下這隻會提高一次),所以我可以打電話給其他一些長期正在運行。

我很難想出一個乾淨的方式來做到這一點。據我所知,INotifyPropertyChanged只跟蹤一個類的屬性變化,而ObservationCollection不知道它的某個項目是否改變了某些東西。

到目前爲止,我嘗試過使用嵌套循環像(僞代碼):

foreach (var course in d.Courses){ 
    foreach (var teacher in course.Teachers){ 
     foreach (var student in teacher.Students){ 
      ((INotifyPropertyChanged)student).PropertyChanged += ... 
     } 
     teacher.Students.CollectionChanged += ... 
    } 
} 

但作爲可以想象,這創造了大量的PropertyChanged事件,因爲每個屬性訂閱的,動作,我想在系辦最終被執行很多次,這是不好的。

然後我使用計時器嘗試(我們每個班都有一個IsDirty()來確定對象是否改變)與間隔設置爲500:

if(department != null && department.IsDirty()){ 
    //call some long running Action here 
} 

雖然這似乎工作,不知何故,我覺得這種方法是錯誤的,我真的很想避免計時器,如果可能的話,我很想聽聽其他的建議和想法!

感謝,

+0

任何更改並運行相同的長時間運行長過程。這個漫長的過程的性質是什麼,你不能更具體一些,並處理財產集中的財產變化? – Paparazzi 2012-04-05 15:41:48

+0

看看該實現的的[那的ObservableCollection還監視在集合中的元素的變化(http://stackoverflow.com/a/269113/620360)。 – LPL 2012-04-05 15:24:50

+0

@LPL,謝謝,這篇文章看起來很有趣,我一定會更多地研究它。 – wliao 2012-04-05 18:10:12

回答

1

這僅僅是一個快速的想法,沒有一個計時器,你能在球場上實現IsDirty事件,&教師類?

例如,教師,內部PropertyChanged的管理員(在學生收藏更改時正確訂閱/取消訂閱)。 當任何學生有一個有效的變化時,所有要做的就是引發IsDirty事件,這個事件都有學生obj作爲參數。

課程將聆聽並捕獲teacher.IsDirty事件,並將提升其自己的課程。IsDirty Where CourseEventArgs =新的CourseEventArgs將有一個課程,教師與學生有髒字段。

在你聽課程IsDirty事件,並解析ARGS Department類...

這樣的想法,似乎這樣做,你有同樣的事情,但不是真的,因爲它是唯一處理任何的PropertyChanged最低級別然後利用您自己的活動將必要信息提供給頂部。這頂班的學生的PropertyChanged行爲實現分離以及廣泛的喋喋不休.. 此外,如果對學生的水平,你做出改變(通過用戶界面,並將其張貼,單擊保存或其他),那麼你可以被升高IsDirty時控制,也許只有一次。

+0

謝謝你的建議,如果我理解正確的話,這將涉及修改的所有類的屬性,當值改變,引發PropertyChanged事件旁邊專門提高IsDirtyEvent,是正確的? – wliao 2012-04-05 18:09:16

+0

是的,爲了讓你有,你就必須創建自己的(公共類的EventArgs :EventArgs的)定製ARGS – 2012-04-05 18:28:07

+0

我們的團隊正在考慮這種做法現在,我會接受,除非別的浮出水面紀念這個。感謝大家的建議。 – wliao 2012-04-10 17:36:35

1

我認爲你仍然需要在單獨的對象級別使用IsDrity位和INotifyPropertyChanged,但爲什麼不擴展ObservableCollection<T>並重寫一些基本方法來處理註冊對象屬性更改?因此,例如,創建類似於:

public class ChangeTrackerCollection<T> : ObservableCollection<T> 
{ 
    protected override void ClearItems() 
    { 
     foreach (var item in this) 
      UnregisterItemEvents(item); 

     base.ClearItems(); 
    } 

    protected override void InsertItem(int index, T item) 
    { 
     base.InsertItem(index, item); 

     RegisterItemEvents(item); 
    } 

    protected override void RemoveItem(int index) 
    { 
     UnregisterItemEvents(this[index]); 

     base.RemoveItem(index); 
    } 

    private void RegisterItemEvents(T item) 
    { 
     item.PropertyChanged += this.OnItemPropertyChanged; 
    } 

    private void UnregisterItemEvents(T item) 
    { 
     item.PropertyChanged -= this.OnItemPropertyChanged; 
    } 

    private void OnItemPropertyChanged(object sender, PropertyChangedEventArgs e) 
    { 
     //TODO: raise event to parent object to notify that there was a change... 
    } 
}