何时从对象中删除事件处理程序

本文关键字:事件处理 程序 删除 对象 何时 | 更新日期: 2023-09-27 18:29:01

所以我在对象的加载事件中注册了一些事件处理程序。

tv.PreviewMouseDown += new MouseButtonEventHandler(SignalScrollViewer_PreviewMouseDown);

但我有两个问题。

  1. 如果加载发生两次,并且它试图再次添加事件处理程序,会有问题吗
  2. 我应该如何处理注销事件?它会在销毁时自动处理注销吗?还是我需要在卸载之类的事件中处理它

何时从对象中删除事件处理程序

  1. 是,这将导致另一个订阅,从而导致处理程序执行两次。您可以在已加载的处理程序中删除已加载处理程序

    MSDN:

    由于用户启动的系统主题更改,控件上可能同时引发Loaded和Unloaded。主题更改会导致控件模板和包含的可视化树失效,进而导致整个控件卸载和重新加载。因此,不能假设只有在通过导航到页面首次加载页面时才发生Loaded。

  2. 如果对象不在了,它就不能引发任何事件,因此无需对此采取任何措施。并且处理程序不会使对象保持活动状态(相反)

如果加载发生两次,并且它试图再次添加事件处理程序,会有问题吗?

该活动将获得多次订阅。您可能需要处理这种情况。

我应该如何处理注销事件?它会在销毁时自动处理注销吗?还是我需要在卸载之类的事件中处理它?

您可以在Unloaded或类似的中注销它。一般来说,您只需要在订阅的事件所在的对象将超过您的生命周期时执行此操作。如果它是您自己的对象(即:从用户控件订阅用户控件中按钮上的事件),则不需要取消订阅。

通常从构造函数内部订阅事件,即在创建tv对象之后立即订阅。如果将它们放在一起,就不可能多次订阅同一个tv对象。

人们会希望在Loaded中注册事件处理程序,并在Unloaded中删除它们,这样任何处理事件的对象都会有一个定义的生存期。因此,人们希望每个Loaded事件在显示控件时只发生一次,然后在从视线中移除控件时发生Unloaded事件。

但是,Loaded可能会引发几次,具体取决于您的布局:Expander会导致Loaded引发两次,但在Expander内部的控件上只会引发一次Unloaded,并且TabControl可能会对不同的TabItems(不同的数据)重用相同的控件,而不会在其间引发Loaded或Unloaded。

我找到了两种方法来解决这个问题:要么使用DataTemplates(这至少在TabControl的情况下有帮助),要么使用DataContextChanged事件来注册/注销事件,这是确保接收事件的对象始终是当前DataContext(即ViewModel)的好方法。

您可能还想查看以下链接,了解有关附加和删除事件处理程序及其他行为的更多信息:http://wpfglue.wordpress.com/2009/12/11/the-sticky-component-framework/