Event Handler problem when event receiver window is closed

Hi there,

I have an issue with events handlers added to a window created dynamically

Let say I have a wMain window with some info, when clicking a button I display a wDetail window

The wDetail window has a recordChanged event, raised when saving the data.
The wMain window refresh the info when a recordChanged event is received.

In wMain I have

Dim w As new wMain
AddHandler w.recordChanged, AddressOf recChanged

The method recChanged is defined as

Sub recChanged (sender as wDetail)
' update info on wMain 
Label.text = sender.TextField.text
End Sub

The wDetail code in the Save Button is

RaiseEvent recordChanged
self.close

Everything’s fine until a user closes the wMain window before saving the data on wDetail.
In this case:

  • the Event recordChanged is fired
  • the method recChanged is called
  • -> the app crashes with a Nil object exception on Label.Text

In debug I see the wMain window (self) but all controls are gone, giving the NilObjectException
So the problem is that wMain window instance is still there but not completely ??

What’s the best way to handle this correctly to avoid these crashes ?
(without checking exceptions at every line)

Using Xojo 2015r1
Crashes on all platforms
I can provide a test app.

Thanks !

Olivier

Implement the CancelClose event in wMain and return True to prevent the closing of wMain.

Also, whenever you use AddHandler with AddressOf, you must have a corresponding RemoveHandler that must execute before the object (in this case, the window) goes away. You can do that in the Close event handler unless there is somewhere more appropriate to your code.

Thanks to both of you.

I’m aware of this but I don’t want to keep them open.

That means keeping a reference to the window which is dynamically created.

This is close to what I have implemented.
As all my windows are based on a class derived from Window where I’m setting a boolean property to true in the Close event and returning from the handlers when true.

I was looking for a more global solution.

Thanks anyway !

Then close the sub-window in CancelClose event and return False.

I see what you’re doing now. You are implementing something like an observer pattern so the detail window can tell the Main window when something has changed, yes?

Instead of AddHandler, look into Delegates. The main window can register its delegate with the detail window and set a flag. When closing the main window, if the flag is true, it can unregister its delegate with the detail window.

You can keep a reference to the detail window using a WeakRef. If the WeakRef returns nil, you will know that the detail window was already closed and there is no need to unregister.

On the other end, the detail window will use the delegate to notify the main window when something changes. No delegate means nothing to notify.

To make this simpler, if the only observer of the detail window is the main window, you can register the main window with the detail window when it opens and have the detail window keep a WeakRef. When the detail window closes, it will check the make sure the WeakRef is still valid and, if so, call the appropriate method in the main window.

Hi Kem,

I’ll have a look at the Delegates.
It seems the right way to go in my case.

Thanks a lot.