How to avoid events on changing values programmatically?

Hello

I have a checkbox in a window with an Action event on it. I want to set the checkbox state programmatically while opening the window. That works fine but the problem is that the Action event triggers (on the checkbox) when I change the checkbox state but the Action event should trigger only if the user changes the checkbox state by mouse or keyboard. I’m confused that the Action event fires while I change the checkbox state programmatically.

You can put LockEvents as Boolean property on the window.

And in the Action event of various of controls you can do

if LockEvents then
return
end if

// some event code here…

Then where you cant to check the checked state you do

LockEvents = true
myCheckBox.Value = something
LockEvents = false

Yes, this happens. You need to work around it. Typically I set a boolean called initialising to true, and then test for that in the event handlers and return immediatly if it has value True. Once I am done initialising all these fields I set it to False. In other words, you need to add some logic to cope with this situation.

1 Like

I often subclass controls and define new events “UserChange”, “ProgramChange”, and “AnyChange”. I differentiate between user-initiated changes and programmatic changes by setting a flag on mousedown, which tells me it’s a user change. Reset the flag on mouseExit, after firing the event, etc.

5 Likes

Thank you all. So confirmed, a workaround is necessary to handle this. So will use one too.Maybe Xojo once is able to differ between user changes and programmatically changes. Obviously there is a need as I’m not the first one discovering this.

This has come up before. I think the point is that there are some circumstances where you’d want an event to fire when a programmatic change is made. And if you don’t want it, it can be worked around.

1 Like

I would expect it the other way around: By default a programmatic change doesn’t trigger an event but there could be a method on each object type called Trigger that would fire an event on the object like the user would trigger it: my object.trigger(“event_name”) or my_object.event_name.trigger(). That way the developer has the full control and doesn’t have to create additional code (workaround) to handle the situation.

This was a design decision made 20+ years ago and it’s not likely to change.

Note that in some situations, OS and user-dependent, a button (or checkbox…) can be clicked with the keyboard, which sounds like it might escape your logic.

I handled this in a similar but different way. basically, my code assumes that any change is caused by the user, unles we know different, and so to set a value w/o triggering the changed event, I subclass all controls and add specific functions to change the value programmatically (with a flag to indicate trigger or not trigger event)

1 Like

Might be nice to have a parameter that specifies the source of the change. Can easily be subclassed as @Julia_Truchsess mentioned, but I’m a big fan of having more functionality in the framework. That being said, it’s probably never gonna happen unless you do it yourself.

1 Like

In certain, more complex situations, I will have an integer that keeps track of the state of things. For example, if an update may also trigger another update, you can get into a situation where a Boolean will not be enough. Instead:

In the code that is doing the update…

updateUnderway = updateUnderway + 1
...update update update...
updateUnderway = updateUnderway - 1

Elsewhere:

if updateUnderway>0 then
     'don't do this when an update is happening
end

Using this method, multiple blocks of code wrapped in updateUnderway+/-1 will guarantee that updates only happen when appropriate. If you only use a Boolean, you’ll run into trouble once your code gets complicated enough that it triggers updates in multiple locations.

I don’t know why you would. For all the information the documentation is lacking, it specifically tells you this is going to happen.

This “don’t raise events when changed programmatically” was done to a single control in Web 2.0 which broke my projects. I’m also aware of at least one other person with a sizable project that this change in behavior caused a problem for. (It has since been corrected.)

I would not be pleased to see this change.

you can also use a status and enumeration instead of a flag and choose what to do at events.

xojo could add a argument where the change came from, user or source code.