1

So I am registering some event handlers in an object's loaded event.

tv.PreviewMouseDown += new MouseButtonEventHandler(SignalScrollViewer_PreviewMouseDown);

but I had two questions.

  1. If loaded occurs twice and it tries to add the event handler again will there be problems?
  2. How should I handle unregistering the event? Will it automatically handle unregistering on destruction or do I need to handle it in some event like unloaded or something?
H H
  • 263,252
  • 30
  • 330
  • 514
James Joshua Street
  • 3,259
  • 10
  • 42
  • 80
  • 1
    No need to unregister it if you still need it to do something when the event is fired. `event` is just a `special delegate` which holds a list of invocations and it's just a member as well as other kinds of members (property, field, method, ...) of your object. So when your object is disposed, it will go away together with the object. – King King Aug 23 '13 at 22:46

4 Answers4

4
  1. Yes that will cause another subscription which causes the handler to execute twice. You can remove the loaded handler inside the loaded handler.

    MSDN:

    Loaded and Unloaded might both be raised on controls as a result of user-initiated system theme changes. A theme change causes an invalidation of the control template and the contained visual tree, which in turn causes the entire control to unload and reload. Therefore Loaded cannot be assumed to occur only when a page is first loaded through navigation to the page.

  2. If the object is gone it cannot raise any events, so no need to do anything about that. And the handler will not keep the object alive (it's the other way around).
H.B.
  • 166,899
  • 29
  • 327
  • 400
  • Might be nice to provide a link to that MSDN page. – Ben Voigt Aug 23 '13 at 23:26
  • I guess it is http://msdn.microsoft.com/en-us/library/system.windows.frameworkelement.loaded.aspx ? – Ben Voigt Aug 23 '13 at 23:29
  • how do I check whether the event already has a handler subscribed to it so that I avoid adding it twice? can I just ParentTreeView.PreviewMouseDown -= new MouseButtonEventHandler(SignalScrollViewer_PreviewMouseDown) when it's not there? or do i need to perform a check? – James Joshua Street Aug 24 '13 at 01:21
  • @JamesJoshuaStreet: You don't need to check first, you can just preventively unsubscribe. However as mentioned i would go with unsubscibing in the handler itself which effectively is a handle-once subscription. – H.B. Aug 24 '13 at 01:29
  • hate to bother you again. but i think I somehow missed bullet point 1 when I saw the post earlier. What exactly do you mean by remove the handler from inside the handler. If it's not too much trouble could you provide an example. – James Joshua Street Aug 29 '13 at 19:22
  • 1
    @JamesJoshuaStreet: [Here's one](http://stackoverflow.com/questions/5958508/fading-out-a-window/5958549#5958549). – H.B. Aug 29 '13 at 19:29
3

If loaded occurs twice and it tries to add the event handler again will there be problems?

The event will get subscribed multiple times. You may want to handle this scenario.

How should I handle unregistering the event? Will it automatically handle unregistering on destruction or do I need to handle it in some event like unloaded or something?

You can unregister it in Unloaded or similar. In general, you only need to do this if object on which the event you're subscribing will live beyond your lifetime. If it's an object within yourself (ie: subscribing to an event on a button within a user control, from the user control), unsubscription isn't required.

Reed Copsey
  • 554,122
  • 78
  • 1,158
  • 1,373
2

One normally subscribes to events from inside the constructor, i.e. immediately after the tv object gets created. If you keep those together, it's not possible to subscribe multiple times to the same tv object.

Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
  • what if you are subscribing to another object's event? is that scenario uncommon? I wanted to have my scrollviewer subscribe to the treeview's mousedown events so that it could handle them in place of the treeview. – James Joshua Street Aug 24 '13 at 01:16
  • @James: That's the scenario I'm talking about. The constructor for the containing user control or window creates both the scrollviewer and treeview, and attaches them together. Subscribing events isn't (based on my WinForms experience -- is WPF that radically different?) something that needs to wait for layout to take place first. – Ben Voigt Aug 24 '13 at 14:04
  • I think that in my case the visual tree connections used to find the parent to subscribe to were not available till the layout finished loading. I know I tried putting it in the constructor at first but i couldn't get Visualtreehelper to find the parent that i wanted. – James Joshua Street Aug 29 '13 at 19:15
2

One would want to register event handlers in Loaded and remove them in Unloaded, so any objects which handle the event would have a defined lifetime. So, one would wish that every Loaded event occurs only once when the control is shown, and is followed by an Unloaded event when the control is removed from sight.

However, Loaded might be raised several times, depending on your layout: Expander causes Loaded to be raised twice, but Unloaded only once on controls inside the Expander, and TabControl might reuse the same controls for different TabItems (different data) without raising Loaded or Unloaded in between.

I found two ways to get around this: Either use DataTemplates (this helps at least in the TabControl case), or use the DataContextChanged event to register / unregister the events, which is a good way to ensure that the object which receives the events is always the current DataContext (i.e. ViewModel).

You might also want to check out the following link for more information on attaching and removing event handlers and other behaviours: http://wpfglue.wordpress.com/2009/12/11/the-sticky-component-framework/

hbarck
  • 2,934
  • 13
  • 16