内置的WPF控件如何管理其附加事件的事件处理程序?

Nic*_*ier 5 wpf events memory-leaks

我知道当您将对象注册到鼠标的附加事件时,您会发生内存泄漏.这就是你需要使用WeakEvent模式的原因.

我对此模式有疑问:如果要使用它,则无法在XAML代码中定义处理程序.

对我而言,这意味着每个代码都会泄漏:

<SomeControl Mouse.MouseDown="MyHandler" />
Run Code Online (Sandbox Code Playgroud)

除非你在代码中显式删除你的处理程序(我怀疑有人这样做).现在有一些我不明白的东西:

<Button Click="MyHandler" />
Run Code Online (Sandbox Code Playgroud)

此代码以某种方式使用Mouse.MouseDown事件的某处来检测按钮上的单击.通过对反射器的一些研究,我发现这个事件使用了UIElement类的MouseDown.当我读到UIElement的代码时,我不明白:没有WeakEventManager!

有人可以解释一下UIElement如何从Mouse.MouseDown接收没有泄漏的事件?

Jos*_*h G 7

在XAML中使用普通处理程序不需要弱引用.

你正在做的是在主控件和该控件中包含的子控件之间创建一个内存引用; 在这种情况下,子控件是按钮.

如果某人维护对主控件的可视树的任何部分的引用,则整个树将保留在内存中,因为它被链接在一起(父/子引用).

现在,如果删除了对此树的所有引用,则父级和子级(主控件和按钮)之间的事件引用并不重要,因为这些控件已通过父/子引用链接.删除所有外部引用后,可以对此控件进行垃圾回收.

XAML中的事件处理程序仅创建内部事件引用.

当外部客户端注册到控件上的事件时,您必须要小心,因为您正在创建一个外部引用,只要链接和客户端存在(除非它是弱引用),它将使控件保持活动状态.

你的问题是关于附加事件.关于附加事件是否导致内存泄漏似乎没有任何明确的文档.在我看来,订阅事件的UI控件包含对事件的引用而不是相反的方式,但我认为静态事件对象必须有某种方式通知控件它已被触发.微软似乎对这一点感到惊讶.