这是对我留下的评论的回复。希望这能回答你的问题,Shimmy。只需发表评论,如果它不能回答您的问题,我会缩短或删除它。
您将需要在您的类上实现 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;博士
现在您可以派生一个从 INotifyPropertyChanged 继承的事件,但使用一个参数,该参数包含一个表示先前值的对象以及属性名称。这会将被触发的事件数量减少到一个,具有类似的功能,并且与 INotifyPropertyChanged 具有向后兼容性。
但是如果你想在设置属性之前处理任何事情(比如属性做了不可逆的更改,或者你需要在设置该变量之前设置其他属性,否则会抛出异常)你将无法做到这一点。
总的来说,这种方法是一种非常古老的做事方式。我会接受 Poker Villian 的回答,并且可以输入无效数据。但不允许保存到数据库。
实体框架有一些优秀的验证代码。您可以通过属性向您的属性添加验证。然后它负责处理这些属性的工作。然后您可以创建一个名为 IsValid 的属性,该属性调用实体框架特定的验证。它还区分了字段错误(如输入错误字符或字符串太长)和类错误(如缺少数据或键冲突)。
然后您可以将 IsValid 绑定到控件验证,当输入无效数据时它们会显示一个红色气泡。或者您可以自己实现 IsValid 验证。但如果 IsValid 为 false,SaveChanges 事件将需要取消保存。
顺便提一句。提供的代码不会编译并且只是伪代码(混合 vb 和 c#)。但我相信它比单独的 c# 更具描述性——准确地显示正在处理的内容。