これは私が残したコメントへの返信です。うまくいけば、これはあなたの質問に答えます、シミー。コメントするだけで、質問に答えられない場合は短縮または削除します。
INotifyPropertyChangingインターフェイスとINotifyPropertyChangedインターフェイスの両方をクラスに実装する必要があります(これらを内部的に実装すると思われるエンティティフレームワークオブジェクトのようなものでない限り)。
また、このプロパティに値を設定する前に、PropertyChangingEventArgsコンストラクターでプロパティの名前を使用して、NotifyPropertyChanging.PropertyChangingイベントを発生させる必要があります。
そして、この値を設定した後、NofityPropertyChanged.PropertyChangedイベントを発生させる必要があります。これも、PropertyChangedEventArgsコンストラクターで発生しているプロパティの名前を使用します。
次に、PropertyChangingイベントとPropertyChangedイベントを処理する必要があります。PropertyChangingイベントでは、値をキャッシュする必要があります。PropertyChangedイベントでは、例外を比較してスローできます。
PropertyChanging / PropertyChangedイベント引数からプロパティを取得するには、relfectionを使用する必要があります。
// PropertyName is the key, and the PropertyValue is the value.
Dictionary <string, object> propertyDict = new Dictionary<object, object>();
// Convert this function prototype to C# from VBNet. I like how Handles is descriptive.
Public Sub PropertyChanging(sender As object, e As PropertyChangingEventArgs) Handles Foo.PropertyChanging
{
if (sender == null || preventRecursion)
{
return;
} // End if
Type senderType = sender.GetType();
PropertyInfo info = senderType.GetProperty(e.PropertyName);
object propertyValue = info.GetValue(sender, null);
// Change this so it checks if e.PropertyName already exists.
propertyDict.Add(e.PropertyName, propertyValue);
} // End PropertyChanging() Event
// Convert this function prototype to C# from VBNet. I like how Handles is descriptive.
Public Sub PropertyChanged(sender As object, e As PropertyChangedEventArgs) Handles Foo.PropertyChanged
{
if (sender == null || preventRecursion)
{
return;
} // End if
Type senderType = sender.GetType();
PropertyInfo info = senderType.GetProperty(e.PropertyName);
object propertyValue = info.GetValue(sender, null);
// Change this so it makes sure e.PropertyName exists.
object oldValue = propertyDict(e.PropertyName);
object newValue = propertyValue;
// No longer needed.
propertyDict.Remove(e.PropertyName);
if (/* some condition */)
{
try {
preventRecursion = true;
info.SetValue(oldValue, null);
Throw New Exception();
} finally {
preventRecursion = false;
} // End try
} // End if
} // End PropertyChanging() Event
これらのメソッドの上に追加するのを忘れたブール値であるPreventRecursionをどのように使用しているかに注意してください。プロパティを以前の値にリセットすると、これらのイベントが呼び出されます。
tl; dr
これで、INotifyPropertyChangedから継承する単一のイベントを派生させることができますが、前の値とプロパティ名を表すオブジェクトを保持する引数を使用します。これにより、発生するイベントの数が1つに減り、同様の機能があり、INotifyPropertyChangedとの下位互換性があります。
ただし、プロパティが設定される前に何かを処理したい場合(たとえば、プロパティが元に戻せない変更を行う場合、またはその変数を設定する前に他のプロパティを設定する必要がある場合、そうでない場合は例外がスローされます)、それを行うことはできません。
全体として、この方法は非常に古い方法です。私はポーカービリアンの答えを受け取り、無効なデータを入力することができます。ただし、データベースへの保存は許可しないでください。
Entity Frameworkには、検証に向けた優れたコードがいくつかあります。属性を介してプロパティに検証を追加します。そして、それらの属性を処理する作業を処理します。次に、EntityFramework固有の検証を呼び出すIsValidというプロパティを作成できます。また、フィールドエラー(間違った文字の入力や文字列の長すぎるなど)とクラスエラー(データの欠落やキーの競合など)の両方を区別します。
次に、IsValidをコントロールの検証にバインドすると、無効なデータが入力されている間、コントロールに赤いバブルが表示されます。または、IsValid検証を自分で実装することもできます。ただし、IsValidがfalseの場合、SaveChangesイベントは保存をキャンセルする必要があります。
ところで。提供されたコードはコンパイルされず、疑似コードのみです(vbとc#を混合)。しかし、c#だけの場合よりもはるかにわかりやすく、処理されている内容を正確に示していると思います。