Event when a DesktopListBox's visible range changes

Is there any event in a DesktopListBox I can use to know that the visible range of items has changed?

In my particular use case I’m going to have a list of rows with several million (often > 100M) rows in it. I don’t care to populate those rows as the cost of the transform required to do that will be prohibitively expensive.

Instead, I’d prefer to simply know what the 100 (or so) visible rows are, and perform a small subset transform of those (caching them) and simply using the PaintCellText event to render from the cached data. As the user moves around and scrolls, I can update the cache in real time.

But, this requires knowing when the visible range of rows has changed. I considered hiding the vertical scrollbar and instead creating my own, but this won’t capture keydown events that end up scrolling, paging, etc.

If there’s nothing like the above, my last consideration is to check the range loaded within the paint event and if the cell being drawn isn’t in the cache I can just load a slightly larger cache area, but this isn’t as desirable.

Certainly nothing with the built in ListBox. I created a grid control with a similar issue in mind. I used a canvas and draw the contents of the current rows onto the control. I then had my own scrollbars, which I set to the datas min and max. When my scrollbars signal a change I cause a repaint. You can implement the keyboard events within the custom control to imitate the listbox.

The general term for what you are describing it “Data on demand” and I have used both of the following to achieve this in various projects:

MacTechnologie’s shareware Data-On-Demand 2.4.2 which performs VERY well even when I pull rows from a remote database. It subclasses the Xojo Listbox and does most of the work for you. Highly recommended if all you need is what you are asking about.

piDog’s DataView control which does SO MUCH more than just also supporting Data On Demand. It does not subclass the Xojo Listbox but instead does its magic using a Canvas control so it supports LOTS of stuff you can’t easily do in a standard Listbox such as variable height rows, cells that span rows or columns, locking columns on the left to act similar to Excel’s “freeze panes”, and way to many other things to mention. It is available in both encrypted source and full source versions. At least check out the demo projects included with the trial.

I use a timer (as a property of the listbox) to track the scrollposition and fetch more data as needed.

You might also want to check out Lazy Loading Data with ListBox : Lazy Loading Data with ListBox – Xojo Programming Blog

I had to add the MouseWheel event to the listbox, and some code to it so mouse scrolling worked.

Function MouseWheel(X As Integer, Y As Integer, deltaX as Integer, deltaY as Integer) Handles MouseWheel as Boolean
  If Listbox1.RowCount <> 0 Then
    
    Var n As Integer = ScrollBar1.Value + deltaY
    ScrollBar1.Value = n.Clamp(0, Data.LastIndex)
    
  End If
  Return False
End Function

The code below is in a global module.

Public Function Clamp(extends  byref i as integer, min as integer, max as integer) As integer
  If i > Max Then i = Max
  If i < Min Then i = Min
  return i
End Function

1 Like

If you need a macOS only solution check out NSTableView from the MBS plugin.

make a containercontrol, with your listbox(with no scrollbar) and a separate scrollbar (or two if you need)
you will then have your event in the scrollbar item, and you can scroll the listbox in sync.