所以我在一个对象的加载事件中注册了一些事件处理程序。
tv.PreviewMouseDown += new MouseButtonEventHandler(SignalScrollViewer_PreviewMouseDown);
但我有两个问题。
答案 0 :(得分:4)
是的,这将导致另一个订阅,导致处理程序执行两次。您可以在加载的处理程序中删除已加载的处理程序。
MSDN:
由于用户启动的系统主题更改,可能会在控件上引发加载和卸载。主题更改会导致控件模板和包含的可视树失效,从而导致整个控件卸载和重新加载。因此,只有在首次通过导航到页面加载页面时才能假定已加载。
答案 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/