Is there a trick to preventing an event from firing.
For example say you have a PopupMenu that has a SelectionChanged event handler that fills another PopupMenu based on the selection in the first PopupMenu. A user selects something in the first popup and then somehting in the second popup and leaves the form.
On the user returning to the form, I want to reset both popups to how they were when the user left. In the Open event for the form I fill the first popup and set it’s selection, fill the second popup and set it’s selection.
Now what happens is, the first popup sees this as a selection change and repeats the process. Depending on how it is written you either get an uneccessary refilling of the second popup or, worse, a duplicaiton of the data is appeneded to the popup.
I can set a flag in code or something to skip my code in the Selection Changed handler, but I am wondering if there is a way to manage this without programming.
Often times I’ll create a property in the window, IsLoading as boolean
Then, in your window’s loading function where you initially set the values of the popup menus/etc, you can set IsLoading to true at the beginning of the method and set it to false at the end (and make sure to set it to false if you’re returning out of the method for any reason).
And then in the event, just use:
if IsLoading= false then
//your code
end if
The same can be used to have to popups that interact. Just have your change event code:
if IsLoading= false then
IsLoading=true
//your code
IsLoading=false
end if
Now if you manually/automatically set one and it modifies the other, the other’s code still won’t fire.
@Tom Iwaniec
Thanks Tom. I am new to Xojo. Justed started using it last week Friday, so forgive me if I am beating a dead horse with this question. I was actually looking for something other than by code.
Having said that, I am wondering about your choice to put the flag as a property of the window. Mine is a WebApp and before I got your asnwer I decided to do the same as you, but created a flag as a property of the session. Any reason I should not have done it that way? I figured that I will be using the property often and it’s scope to me seems to be most appropriate in the session.
Expanding on this, how do yo handle things when you have more than one object that needs to skip events? The flag needs to be reset back to false after the window has loaded and all the events have fired. With a single object where the flag is used, it’s easy, just reset the flag in the else of the if flag statement. If however there is another object that can mess things up the flag would not be set if it fired after the flag is reset by another object. I guess that answers my question about where to put the flag property. In this case I would think the only solution would be to create flag properities in the window/webform specifically targetting each object that requires it.
Thinking outloud really helps me resolve some issues.
John
In the open event do this:
me.enabled = false
me.listindex = somevalue
me.enabled = true
In the Action event I have this:
if me.enabled = false then return
//do something with value.
This way there’s no need for extra variables though you do have to enabled/disable the controls. This can be done en mass however so that’s not a big deal (most of the time)
@Bob Keeney
Bob, sorry I am not following you. In what control or object are these events?.
There may be some hacks for each platform that prevent execution of the event. Could be kind of messy…
You will always have some programming to do, but you could instead of adding the event handler in the IDE add it by code with AddHandler so you can remove it at will, effectively preventing its execution in the target method.
IMHO a flag remains the simplest option.
Okay. I’ll backup a bit.
You say you want to prevent the Action even happening. Well, you can’t. In the current framework it will happen as soon as you change the value. All you can do it learn to ignore it.
In the example of a PopupMenu open event you can do something like this. Load the list and set the ListIndex. However, doing that will fire the Change event. So what I do is disable it before setting the ListIndex.
PopupMenu1.Open event
[code]Sub Open()
me.addRow “One”
me.addRow “Two”
me.addRow “Three”
me.enabled = false
me.ListIndex = 0
me.enabled = true
End Sub
[/code]
Then in the Change event I return immediate if the control is disabled. If not, I process it.
PopupMenu1.Change event
[code]Sub Change()
if me.Enabled = false then return
msgbox Me.text
End Sub
[/code]
Hopefully that makes sense.
Hmmm. I may have learned something here about events. I am following you now, but I am surprised to see you disable and enable the popup in the open event. Don’t the events fire in some kind of sequence? In 3 lines you set the popup enabled = false and back to true. Does the Popup change event fire as soon as the the listIndex of the popup is changed and the Open event pauses until the popup change event is complete???
Seeing what you are doing, and I like it, I would have enabled the popup in it’s change event before the return.
Never expect any set order for events. It is often reminded here by Xojo engineers. If I remember right, the only order one can expect is that a window Open event happens after the controls ones.