Ответ 1
Это ответ на комментарий, который я оставил. Надеюсь, это ответит на ваш вопрос, Шимми. Просто комментарий, и я сокращу его или удалю, если он не ответит на ваш вопрос.
Вам потребуются как INotifyPropertyChanging, так и INotifyPropertyChanged интерфейсы, которые будут реализованы в вашем классе (если только это не похоже на объект фреймворка сущности, который, как я считаю, реализует их внутренне).
И прежде чем вы установите значение для этого свойства, вам нужно поднять событие NotifyPropertyChanging.PropertyChanging, используя имя свойства в конструкторе PropertyChangingEventArgs.
И после того, как вы установите это значение, вам нужно поднять событие NofityPropertyChanged.PropertyChanged, снова используя имя свойства, которое создается в конструкторе PropertyChangedEventArgs.
Затем вам нужно обработать события PropertyChanging и PropertyChanged. В событии PropertyChanging вам нужно кэшировать значение. В событии PropertyChanged вы можете сравнить и выбросить исключение.
Чтобы получить свойство из аргументов eventChanging/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, который является логическим, я забыл добавить выше этих методов? Когда вы reset свойство вернется к своему предыдущему значению, эти события будут вызваны.
ТЛ; дг
Теперь вы можете получить одно событие, которое наследуется от INotifyPropertyChanged, но использует аргумент, который содержит объект, представляющий предыдущее значение, а также имя свойства. И это уменьшит количество запущенных событий до одного, будет иметь аналогичную функциональность и будет иметь обратную совместимость с INotifyPropertyChanged.
Но если вы хотите обработать что-либо до того, как свойство будет установлено (скажем, свойство делает необратимое изменение или вам нужно настроить другие свойства перед установкой этой переменной, в противном случае будет выбрано исключение), вы не сможете сделать что.
В целом, этот метод - очень старый способ делать вещи. Я бы ответил на Poker Villian и имел недействительные данные, которые можно ввести. Но запретите сохранение в базе данных.
В Entity Framework есть отличный код для проверки. Вы добавляете подтверждение к своим свойствам через атрибуты. И затем он заботится о работе по обработке этих атрибутов. Затем вы можете создать свойство IsValid, которое вызывает специфическую проверку Entity Framework. Он также различает как полевые ошибки (например, ввод неправильных символов, либо слишком длинная строка), так и ошибки класса (например, отсутствие данных или конфликтующие ключи).
Затем вы можете привязать IsValid к проверке проверки, и они будут отображать красный пузырь, пока будут введены неверные данные. Или вы можете просто реализовать проверку IsValid самостоятельно. Но если IsValid является ложным, для события SaveChanges потребуется отменить сохранение.
кстати. Предоставленный код не будет компилироваться и только псевдокод (смешение vb и С#). Но я считаю, что это гораздо более описательно, чем только С# - показывая точно, что обрабатывается.