コードでPropertyObserverクラスを使用して、PropertyChanged
イベント処理での 文字列比較を回避し、null
またはstring.Empty
その引数としての処理を除外しています (これは、オブジェクトのすべてのプロパティが変更されたことを示します)。
このクラスはPropertyChangedEventManager
、ターゲット オブジェクトにコールバックを登録するために使用し、ソース オブジェクトでイベントが呼び出されるIWeakEventListener
たびに応答するように実装します。PropertyChanged
しかし、単体テストの作成中にIWeakEventListener.ReceiveWeakEvent()
、登録されたコールバックの数として N を使用して、 が N 回呼び出されることがわかりました。これは、PropertyChanged イベントで有効なプロパティ名が指定された場合ではなく、null または string.Empty が指定された場合にのみ発生します。
なぜこれが起こっているのか、それを修正する方法を知っている人はいますか? 私の目標は、null が指定されたときに登録済みハンドラーの foreach を 1 回実行することです。これにより、ソース オブジェクトのすべてのプロパティを取得してターゲット オブジェクトを更新できます。しかし、ReceiveWeakEvent()
が N 回呼び出されると、foreach は N 回繰り返されます!
それを説明するために、以下は PropertyObserver クラスとソース クラスの簡略化されたバージョンです (実装には MVVM Light を使用しています) ObservableObject
。INotifyPropertyChanged
public class PropertyObserver : IWeakEventListener {
public bool ReceiveWeakEvent(Type managerType, object sender, EventArgs e) {
if (managerType == typeof(PropertyChangedEventManager)) {
string propertyName = ((PropertyChangedEventArgs)e).PropertyName;
if (string.IsNullOrEmpty(propertyName)) {
Console.WriteLine ("Foreach registered handlers and invoke one by one");
} else {
Console.WriteLine ("Invoke handler for property {0}", propertyName);
}
return true;
}
return false;
}
}
public class ViewModel : ObservableObject {
private int mProp1;
private int mProp2;
public int Prop1 {
get { return mProp1; }
set {
mProp1 = value;
RaisePropertyChanged("Prop1");
}
}
public int Prop2 {
get { return mProp2; }
set {
mProp2 = value;
RaisePropertyChanged("Prop2");
}
}
public void RaiseAllPropertyChanged() {
RaisePropertyChanged(null);
}
}
コンソール アプリの Main では、次のように呼び出すことができます。
var vm = new ViewModel();
var obs = new PropertyObserver();
// Normally this is done inside the PropertyObserver class.
PropertyChangedEventManager.AddListener(vm, obs, "Prop1");
PropertyChangedEventManager.AddListener(vm, obs, "Prop2");
vm.Prop1 = 1; // Results in a console line "Invoke handler for property Prop1"
vm.Prop2 = 2; // Results in a console line "Invoke handler for property Prop2"
// Results in two console lines: "Foreach registered handlers and invoke one by one", expected is only 1!
vm.RaiseAllPropertyChanged();