2012-04-05 43 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... 
    } 
}