Thanks: I’ve implemented this for the next release: https://feedback.objo.dev/feature/1373
ListBox now has:
ScrollX As Integer — read/write horizontal offset in logical points.
ScrollY As Integer — read/write vertical offset in logical points.
TopVisibleRowIndex As Integer — read/write convenience property for row-based navigation.
ScrollChanged() — fires when the scroll position changes.
HasHorizontalScrollbar As Boolean
HasVerticalScrollbar As Boolean
HideUnneededScrollbars As Boolean
I kept ScrollX and ScrollY symmetrical: both use logical-point offsets and are clamped to the available scrolling range. For code that wants to work in rows rather than points, TopVisibleRowIndex provides that behaviour explicitly.
Scroll positions may also be assigned before the ListBox has opened; the requested position is applied once its layout and scrollable range are known. Changing the position does not alter the row selection.
ScrollBox already had ScrollX, ScrollY, ScrollTo(), ScrollChanged, and the two per-axis scrollbar properties. It now also has HideUnneededScrollbars.
HideUnneededScrollbars defaults to True. Setting it to False keeps enabled scrollbars visible even when the current content fits. Setting either HasHorizontalScrollbar or HasVerticalScrollbar to False disables that scrolling direction completely.