2012-04-05 14 views
2

我々は、WPFアプリケーションを持って、私はコースののObservableCollectionを持って、私はそれで、部門オブジェクトを持っているのは、言わせて、各コースの内側に、私は教師ののObservableCollectionを持っており、各教師の内側に、私は学生ののObservableCollectionを持っている:WPFの親オブジェクトからの子供の変化を検出する方法は?

Department.cs ----のObservableCollectionコース

Course.cs ----のObservableCollection教師

Teacher.cs ----のObservableCollection学生

など

Student.cs ----名前、年齢、

これらの4つのクラスすべての実装INotifyPropertyChangedのは、彼ら自身によって正常に動作している、私が達成したいことは部門オブジェクトグラフ内のものは、それかどうか、変更されるたびに生徒の年齢が変更された、新しいコースが追加された、または教師が削除された、何か、全く知りたい、理想的にはDepartmentChangedのようなイベントを介して(理想的にはこれを1回だけ募る)実行中のアクション。

私はそれを行うためのきれいな方法を思いついています。 INotifyPropertyChangedはクラスのプロパティの変更のみを追跡し、ObservationCollectionはそのアイテムの1つが何か変更されているかどうかわかりません。すべてのプロパティがそれにサブスクライブ以来のPropertyChangedイベントの

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

しかし、想像することができるように、これは作成した多く、およびアクションが、私は教室でやってみたかった:

は、これまでのところ私は(擬似コード)のようなネストされたループを試してみました結局、何度も何度も実行されてしまいましたが、これは悪いことです。

私はその後、500に間隔を設定して(オブジェクトが変更されたかどうかを判断するために私たちのクラスのそれぞれは、(IsDirtyを持っている))、タイマーを使用してみました:

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

これが動作しているようですが、どういうわけか私は感じますこのアプローチは間違っています。可能であればタイマーを避けたいと思っています。私は他の提案やアイデアを聞きたいです!

おかげで、

+0

変更して同じ長時間実行する長い手順を実行します。この長い手順の性質は、あなたがもう少し具体的でなく、プロパティセットのプロパティ変更に対処することができないものは何ですか? – Paparazzi

+0

[ObservableCollectionのこの実装を見て、コレクション内の要素の変更も監視します](http://stackoverflow.com/a/269113/620360)。 – LPL

+0

@LPL、ありがとう、そのポストは面白そうだ、私は間違いなくもっとそれを勉強します。 – wliao

答えて

1

これは単なる迅速なアイデアですが、タイマーなしで、あなたは、コース上&教師のクラスをIsDirtyイベントを実装することができますか?

たとえば、Teacher、PropertyChangedのマネージャは内部で(学生コレクションが変更されたときに適切にサブスクライブ/サブスクライブ解除します)。 学生が有効な変更を行った場合、すべてが行う必要があるのは、学生objをパラメータとして持つIsDirtyイベントを発生させることだけです。

コースは、教師を聴いてキャプチャします。アイズダーティイベント、および独自のコースを開催します.IsDirty where CourseEventArgs = new CourseEventArgsには、汚れたフィールドを持つ生徒の教師がいます。あなたがコースIsDirtyイベントに耳を傾け、引数を解析部門クラスで

...

このアイデア、それだけで任意のにPropertyChangedを処理するためではなく、本当にあなたが持っている同じことをやっているようだが、最も低いレベルは、あなた自身のイベントを利用して、必要な情報をトップにバブリングします。生徒のPropertyChangedビヘイビアの実装と広範囲なチャタリングからトップクラスを分離します。 また、学生レベルでUIを変更して保存したり、何かをクリックしたりすると、IsDirtyが発生しているときを制御できます。多分一度だけ。

+0

提案がありがとう、私は正しくこれは、PropertyChangedイベントを引き上げるの横に、値が変更されたときに特に、IsDirtyEventを発生させるすべてのクラスのプロパティを変更する必要がありますか、それは正しいですか? – wliao

+0

はい、カスタムargsを持たせるには、自分自身(public class EventArgs :EventArgs)を作成する必要があります –

+0

私たちのチームはこのアプローチを検討しています。みなさん、おかげさまで提案に感謝します。 – wliao

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... 
    } 
} 
関連する問題