PropertyChangedEventHandler如何工作?
这是一个非常简单的问题,但我想知道是否有人可以解释第4行实际上在做什么? 所以第一行给处理程序一个事件。 我真的不知道在什么情况下处理程序将返回null或最后一行的作用。
当你传递处理程序你的对象和哪个属性发生了变化时,它对它们有什么影响?
PropertyChangedEventHandler handler = PropertyChanged; //property changed is the event if (handler != null) { handler(this, new PropertyChangedEventArgs(name)); }
我假设我使用它来获取此代码,但我想了解它正在做什么。
如果你刚刚做了:
PropertyChanged(this, new PropertyChangedEventArgs(name))
如果没有人订阅PropertyChanged
事件,你会得到一个NullReferenceException
。 要抵消这一点,你需要添加一个空检查:
if(PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(name)) }
现在,如果您使用multithreading,则可以取消订阅null检查和事件调用,因此您仍然可以获得NullReferenceException
。 为了处理这个问题,我们将事件处理程序复制到临时变量
PropertyChangedEventHandler handler = PropertyChanged; if (handler != null) { handler(this, new PropertyChangedEventArgs(name)); }
现在,如果某人取消订阅该事件,我们的临时变量handler
仍将指向旧函数,此代码现在无法抛出NullReferenceException
。
大多数情况下,您会看到人们使用关键字var
代替,这使得您无需输入完整类型的临时变量,这是您在代码中最常见到的表单。
var handler = PropertyChanged; if (handler != null) { handler(this, new PropertyChangedEventArgs(name)); }
PropertyChanged
是根据接口中的定义声明的事件:
public event PropertyChangedEventHandler PropertyChanged;
这样定义的事件实际上是事件处理程序列表的语法糖,您可以通过订阅添加委托(即对函数的引用),或通过取消订阅删除委托。
现在,当您调用一个事件,即PropertyChanged(...)
,内部发生的事情是该内部列表中的每个委托都使用参数单独调用。 这将告诉您事件的所有订阅者事件发生。
现在, handler
变量的全部原因是, PropertyChanged
可以为null。 如果没有订阅它,那么调用事件(或者更确切地说是事件处理程序列表)将不起作用,因此这只是一种确保您可以实际执行处理程序的方法。
如果没有处理程序订阅该事件 ,则handler
可以为null,第四行引发给定属性名称的事件(执行所有已订阅的处理程序)。
通常,当您使用绑定时,WPF框架将订阅PropertyChanged
,因此它可以在绑定属性更改后更新绑定。