【问题标题】:how does PropertyChangedEventHandler work?PropertyChangedEventHandler 是如何工作的?
【发布时间】:2013-07-19 01:10:25
【问题描述】:

这是一个非常简单的问题,但我想知道是否有人可以解释第 4 行实际上在做什么?所以第一行给处理程序一个事件。我真的不知道在什么情况下 handler 会返回 null 或者最后一行做什么。

当您向处理程序传递您的对象以及更改了哪个属性时,它对它们做了什么?

PropertyChangedEventHandler handler = PropertyChanged; //property changed is the event

if (handler != null)
{
    handler(this, new PropertyChangedEventArgs(name));
}

我假设我用它来获取这个code,但我想完全了解它在做什么。

【问题讨论】:

  • 没有上下文很难说。你用的是什么框架?这不是 BCL 的一部分,它可能是您正在检查/使用的一些 MVVM 框架。
  • 这对PropertyChangedEventHandler 来说并没有什么特别之处。这就是处理程序的工作方式。
  • Will 的评论毫无意义。这被标记为 WPF。 PropertyChangedEventHandler 在 System.ComponentModel 中。没有 MVVM 框架之类的东西——MVVM 是一种对 WPF 有用但不是必需的架构模式。无论如何,这个问题是关于事件处理程序如何在 C# 中工作的,答案并不特定于任何特定的事件或框架。
  • “第一行给处理程序一个事件”——不,它声明了一个变量handler,并用PropertyChanged的值初始化它……这可能是空的。

标签: c# wpf events propertychanged


【解决方案1】:

如果你刚刚这样做:

PropertyChanged(this, new PropertyChangedEventArgs(name))

如果没有人订阅事件PropertyChanged,您将获得NullReferenceException。为了解决这个问题,您添加了一个空检查:

if(PropertyChanged != null)
{
    PropertyChanged(this, new PropertyChangedEventArgs(name))
}

现在,如果您使用多线程,有人可以在 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));
  }

【讨论】:

  • 在竞争条件下,不会复制处理程序然后调用刚刚指定的不应再调用的函数吗?这只是公认的经商方式,还是我遗漏了什么?
  • @ZachMierzejewski 是的,这是预期的行为。订阅者有责任知道,即使在多线程情况下取消订阅,您仍然可以获得对该方法的最终调用。 .NET 中内置的类的所有事件都遵循这种模式。
【解决方案2】:

PropertyChanged 是这样声明的事件,根据它在接口中的定义:

public event PropertyChangedEventHandler PropertyChanged;

Events 这样定义的实际上是事件处理程序列表的语法糖,您可以通过订阅添加委托(即对函数的引用),或通过取消订阅删除委托。

现在,当您调用一个事件时,即PropertyChanged(...),那么内部发生的情况是,该内部列表中的每个委托都被单独调用并带有参数。这将告诉您事件的所有订阅者该事件发生了。

现在,handler 变量的全部原因是,PropertyChanged 可以为空。如果没有订阅它,那么调用事件(或者更确切地说是事件处理程序列表)将不起作用,因此这只是确保您可以实际执行处理程序的一种方式。

【讨论】:

    【解决方案3】:

    handler 可以为 null 如果没有处理程序是 subscribedevent,第四行引发给定属性名称的事件(执行所有订阅的处理程序)。

    通常 WPF 框架会在您使用绑定时订阅PropertyChanged,因此一旦绑定的属性发生更改,它就可以更新绑定。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-25
      • 1970-01-01
      • 2014-08-13
      • 2011-04-05
      • 2011-04-13
      相关资源
      最近更新 更多