Initializing controls from DB only when they appear

I’m building an app with several tabs, each of which includes a DesktopListbox with potentially thousands of rows.

I got my first tab working and substantially feature-complete. The listbox is populated in its Opening event.

Now I’m building the second tab and, as I feared, placing a MessageBox in the Opening event of the 2 listboxes proves that the Xojo framework is cycling through all controls and initializing them when the app’s single window is displayed, whether or not particular controls are visible or not (based on what tab is initially selected).

This means I’ll have 10 or so listboxes initializing on startup, running blocking queries and populating themselves, doing sorts, etc.

The actual use case is that certain tabs will be used far more often than others, some seldom. I don’t want to burden memory or slow down start up time getting everything going whether I need it or not. I would prefer any DB-driven initialization of each control be done the first time they are displayed.

Near as I can figure, then, what I need to do is move the initialization logic from the individual control Opening events to some event on the tabcontrol. However, I am not clear what that would be. PanelChanged, presumably, could then call a method to initialize controls for that panel. At this point I’m not sure if that fires for the initially-displayed panel, or only when the user changes panels.

I’m just wondering what others consider best practice here.

This is basically how I handle this.

  1. Create a method that fills the Panel that is made current
  2. Set the panel to display when the control has been created by setting SelectedPanelIndex
  3. Each time a Panel is made current, the fields are updated

You may also add a property that is set to True when Panel X has already been updated. If the user move to a different record, then all Panel property should be set to False. This way if the property is True and the user switches back to a Panel already filled, no need to call the method.



Use many windows instead of many panels.

Not knowing what the software do, it is a bit difficult to give advices.

But having many panels will result in ListBox contents comparison difficule / easier if there are in many Windows…

Also, the user open a Window when (s)he needs it, so your trouble populating all tabs on Window Open time vanishes…

At last, you may use a Label or a TextField to give reports instead of MessageBox who stops the application running…
(Not knowing what the software do, make it a bit difficult to give advices.)

Mostly I’m just wanting to minimize app startup overhead and the attendant DB surge. For this app, which is an internal app and a learning experience, I really don’t need to worry about it that much but I am just trying to force myself to think these issues through because I’m interested in building Xojo apps for profit as well as fun.

The pattern I am seeing is that controls in general don’t have event hooks for when they are made visible, just a post-construction event (Opening) and selection changed events that literally fire on user selection so for example don’t fire when the first tab displays on startup (because it’s not user-selected)…

You are right that separate windows vs tabs would alleviate this issue but that isn’t always the best metaphor for every app. And when either metaphor would serve, it might not be client preference.

Anyway I’ve worked out a solution in my head last night which I’ll test out today. I’m sure something can be worked out that isn’t a maintenance nightmare.

What I’ve worked out is basically:

  1. Move code I originally had in Opening event of specific controls (mostly DesktopListbox-derived) to a method of the window.

  2. For whatever is on Tab 0, call that method from the Opening event of relevant controls, since tab 0 will be shown on startup and it’s structured such that it only needs to be called once.

  3. Otherwise call it from the PanelChanged event of the DesktopTabPanel, in a Select Case Me.SelectedPanelIndex that has cases for tabs >= 1

In this fashion, initializations are only done the first time the panel is shown. Each initialization method checks (typically for a zero RowCount in the relevant listbox) to see if it’s already been run, and exits if it has.

The main issue I have with this is the dependence on SelectedPanelIndex. If I reorder or add panels, I will have to update the Select Case. I would rather build the Select Case around the caption / name of the selected panel rather than the ordinal index. Then the logic only needs updating if I change the button text.

I can’t find offhand that this is exposed in the API. It either isn’t, or it’s in some non-intuitive place. Anyone know? In the Xojo IDE, it is exposed in the UI for defining and reordering tabs by name. Surely that info is available programmatically.

NVM, found it: CaptionAt(n)

My life is complete, lol