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

时间:2013-08-23 22:44:30

标签: c# wpf xaml

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

tv.PreviewMouseDown += new MouseButtonEventHandler(SignalScrollViewer_PreviewMouseDown);

但我有两个问题。

  1. 如果加载发生两次并且它再次尝试添加事件处理程序会有问题吗?
  2. 如何处理取消注册活动?它是否会在销毁时自动处理取消注册,还是需要在卸载或其他事件中处理它?<​​/ li>

4 个答案:

答案 0 :(得分:4)

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

    MSDN

      

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

  2. 如果对象消失,则无法引发任何事件,因此无需对此进行任何操作。并且处理程序不会使对象保持活动状态(反之亦然)。

答案 1 :(得分:3)

  

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

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

  

我应该如何处理取消注册活动?它是否会在销毁时自动处理取消注册,还是需要在卸载或其他事件中处理它?<​​/ p>

您可以在Unloaded或类似地方取消注册。一般情况下,只有在您订阅的事件将超出您的生命周期的对象时,您才需要这样做。如果它是你自己内的一个对象(即:在用户控件中订阅一个按钮上的事件,来自用户控件),则不需要取消订阅。

答案 2 :(得分:2)

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

答案 3 :(得分:2)

一个人希望在Loaded中注册事件处理程序并在Unloaded中删除它们,因此处理该事件的任何对象都将具有已定义的生命周期。因此,人们希望每个Loaded事件仅在显示控件时发生一次,并且当控件从视线中移除时后跟一个Unloaded事件。

但是,根据您的布局,可能会多次引发Loaded:Expander导致Loaded被引发两次,但是在Expander内的控件上只卸载一次,而TabControl可能会为不同的TabItem(不同的数据)重用相同的控件而不会提升之间的加载或卸载。

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

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