这是我回复留言的内容。希望这能回答你的问题,Shimmy。如果没有回答到你的问题,请随时留言并告诉我,我会进行简化或删除。
要实现类的绑定通知,需要同时实现INotifyPropertyChanging和INotifyPropertyChanged接口(除非它是类似于实体框架对象那样已经内部实现了这些)。
在设置属性值之前,需要使用PropertyChangingEventArgs构造函数中该属性的名称来触发NotifyPropertyChanging.PropertyChanging事件。
在设置完值后,需要再次使用PropertyChangedEventArgs构造函数中该属性的名称来触发NofityPropertyChanged.PropertyChanged事件。
然后,您需要处理PropertyChanging和PropertyChanged事件。在PropertyChanging事件中,您需要缓存该值。在PropertyChanged事件中,则可以对其进行比较并抛出异常。
要从PropertyChanging/PropertyChanged事件参数中获取属性,需要使用反射技术。
Dictionary <string, object> propertyDict = new Dictionary<object, object>();
Public Sub PropertyChanging(sender As object, e As PropertyChangingEventArgs) Handles Foo.PropertyChanging
{
if (sender == null || preventRecursion)
{
return;
}
Type senderType = sender.GetType();
PropertyInfo info = senderType.GetProperty(e.PropertyName);
object propertyValue = info.GetValue(sender, null);
propertyDict.Add(e.PropertyName, propertyValue);
}
Public Sub PropertyChanged(sender As object, e As PropertyChangedEventArgs) Handles Foo.PropertyChanged
{
if (sender == null || preventRecursion)
{
return;
}
Type senderType = sender.GetType();
PropertyInfo info = senderType.GetProperty(e.PropertyName);
object propertyValue = info.GetValue(sender, null);
object oldValue = propertyDict(e.PropertyName);
object newValue = propertyValue;
propertyDict.Remove(e.PropertyName);
if ()
{
try {
preventRecursion = true;
info.SetValue(oldValue, null);
Throw New Exception();
} finally {
preventRecursion = false;
}
}
}
注意我如何使用了PreventRecursion,这是一个布尔值,我之前忘记在这些方法之前添加了吗?当你将属性重置回其先前的值时,这些事件将被重新调用。
简而言之,
现在您可以派生一个单一的事件,该事件继承自INotifyPropertyChanged,但使用一个参数,该参数包含表示先前值以及属性名称的对象。这将把触发的事件数量减少到一个,并具有类似的功能,并且与INotifyPropertyChanged向后兼容。
但是,如果您想在属性设置之前处理任何内容(例如,属性执行不可逆更改或者您需要在设置该变量之前设置其他属性,否则会引发异常),则无法这样做。
总体而言,这种方法非常古老。我会采用Poker Villian的答案,并允许输入无效数据。但是禁止保存到数据库。
Entity Framework具有一些出色的代码用于验证。您可以通过属性向属性添加验证。然后它会处理处理这些属性的工作。然后,您可以创建一个名为IsValid的属性,该属性调用特定于Entity Framework的验证。它还区分字段错误(例如输入错误字符或字符串过长)和类错误(例如缺少数据或冲突键)。
然后,您可以将IsValid绑定到控件验证,并在输入无效数据时显示红色气泡。或者您可以自己实现IsValid验证。但是,如果IsValid为false,则SaveChanges事件需要取消保存。
顺便说一下。提供的代码将无法编译,仅为伪代码(混合vb和c#)。但我认为它比仅使用c#更具描述性-显示正在处理的内容。
CancelEventArgs
继承,但它应该做的是我的另一个请求,即提供候选值(获取当前方法属性的简单方法是具有相当大的性能成本)。 - Shimmy Weitzhandler