2

WPFアプリケーションがあります。たとえば、Departmentオブジェクトがあり、その中にコースのObservableCollectionがあり、各コース内にObservableCollection of Teachersがあり、各Teacher内にObservableCollectionofStudentがあります。

Department.cs----ObservableCollectionコース

Course.cs----ObservableCollection教師

Teacher.cs----ObservableCollectionの学生

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

これらの4つのクラスはすべてINotifyPropertyChangedを実装し、それ自体で正常に機能しています。私が達成したいのは、Departmentオブジェクトグラフ内の何かが変更されたとき、学生の年齢が変更されたとき、新しいコースが追加されたとき、教師が削除されたときなどです。とにかく、私はそれについて知りたいのですが、理想的にはDepartmentChangedのようなイベントを介して(そして理想的にはこれは一度だけ発生します)、他の長期的なアクションを呼び出すことができます。

私はそれを行うためのクリーンな方法を思い付くのに苦労しています。INotifyPropertyChangedはクラスのプロパティ変更のみを追跡し、ObservationCollectionはそのアイテムの1つが何かを変更したかどうかを認識しないことを理解しています。

これまでのところ、(擬似コード)のようなネストされたループを試しました:

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イベントが作成され、Departmentで実行したいアクションが何度も実行されることになり、これは悪いことです。

次に、間隔を500に設定してタイマー(各クラスにIsDirty()があり、オブジェクトが変更されたかどうかを判断します)を使用してみました。

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

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

ありがとう、

4

2 に答える 2

1

これは、タイマーなしの簡単なアイデアです。コースと教師のクラスにIsDirtyイベントを実装できますか?

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

コースは、teacher.IsDirtyイベントをリッスンしてキャプチャし、独自のコースを作成します。IsDirtyここで、CourseEventArgs = new CourseEventArgsには、ダーティフィールドを持つCourse、TeacherwithStudentがあります。

Departmentクラスでは、Course IsDirtyイベントをリッスンし、引数を解析します...

このアイデアは、あなたが持っているのと同じことをしているように見えますが、実際にはそうではありません。これは、PropertyChangedを最下位レベルでのみ処理し、独自のイベントを使用して必要な情報を最上位にバブルするためです。これにより、トップクラスがStudentのPropertyChanged動作の実装や広範なおしゃべりから分離されます。また、学生レベルで変更を加えた場合(UIを介して投稿し、[保存]をクリックするなど)、IsDirtyが発生するタイミングを制御できます。 1回だけ。

于 2012-04-05T16:42:11.323 に答える
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...
    }
}
于 2012-04-06T15:49:05.743 に答える