Update a weblistbox without causing a selection changed event

I had a rather stupid routine that when a new element is to be added to a weblistbox, it deletes all the rows and then repopulates the weblistbox.
this has one side effect which is rather troublesome… and that is that doing this causes the selection changed event to be fired for that weblistbox.

If I have two arrays of strings, one being the current contents and another being the new contents.
How can i syncronize the listbox such that it keeps its selection and adds what ever is new and possibly deletes what is necessary and doesn’t generate a selection changed event ‘unless’ the selected row no longer exists…

Why are you manipulating the contents in a separate array rather than directly adding/removing the row? (you may have a valid reason, just needing to understand the requirement).

Providing that the above is necessary, and assuming you already have the code/logic that re-sets the current selection, you could create a boolean property that you set when updating the listbox, and check that property in the selection changed event to determine if you should act on or ignore the selection change. You can roll the logic of determining if the selected row no longer exists into that as well.

After using realbasic/xojo for years, I’ve tended to run into these situations a lot, and I end up subclassing most of the controls. For example, I have a Checkbox subclass where I can set the .value parameter and optionally choose to block the resulting .Action event.

For your listbox, I’d do something similar:

Sub cListbox.UpdateFromArray(newItems() as string, blockSlectionChangedEvent as boolean = false)
  bBlockEvents = true
  me.DeleteAllRows
  ... update the list items...
  bBlockEvents = false
End Sub

Event cListbox.SelctionChanged
  if (bBlockEvents) then return
  SelectionChanged ' trigger the event

There is no possibility that event queues might exist and mess this up?

I’m confused.
I have several instances of myWebListBox on my web page.
One of those (not the one that was giving me issues) is now complaining.

Must I define a new event in MyWebListBox class called SelectionChanged?

If you are doing multi-threaded programming, then you do have to be careful about re-entrancy, because the framework will yield at a loop boundary. If you aren’t, then it shouldn’t be a problem. I may not be understanding what you mean by “event queues” though - can you say more?)

[quote=23709:@Brian O’Brien]I’m confused.
I have several instances of myWebListBox on my web page.
One of those (not the one that was giving me issues) is now complaining.
Must I define a new event in MyWebListBox class called SelectionChanged?[/quote]

Correct, that should fix it, and then make sure that you put the code I provided into the Class, not in the Instance’s event.

Also, there’s no rule that the new event has to be named “SelectionChanged”, in fact in some of my classes I’ve added new events for clarity:

  • SelectionChangedByCode (this fires when the selection changes due to program code)
  • SelectionChangedByUser (this fires only when the user has changed the selection)

Or sometimes:

  • SelectionChanged(byUser as boolean) ’ the byUser variable is true only when the change was made by the user’s actions, not when it was changed by code.

etc.

The web list box doesn’t seem to allow me to change the style that the selected row is.
I tried setting the me.CellStyle(me.ListIndex, c) in the selection changed event but i only get the default style.

While this is an old thread, I ran across it while researching something else and thought I’d throw my solution out there for folks. I handle this the same way I do for popup menus, which also can become recursively problematic if you have things happen when the selection changes.

Each control already has a built-in boolean property called “enabled”. Whenever you are programmatically altering the listbox or popup menu (etc), set this value to False, and then set it back to True when you have finished making your changes. Like so:

Sub LoadList() ListBox1.Enabled = False ... ListBox1.Enabled = True End Sub

Then, in your “SelectionChanged” event, have it check that property before forwarding any actions. For example:

Sub SelectionChanged() If me.Enabled = False Then Return ... End Sub

This simple solution should prevent the unwanted behaviors in most circumstances without having to create a bunch of messy work-around code.

If you are multi-threading, then keep in mind that you should never (and I mean never, ever, ever) manipulate GUI controls outside of the main thread. Instead, you should have any background threads place their changes into storage classes, and then have any control updates occur on the main thread.