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