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.
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.
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 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.