| title | Scrolling |
|---|
XenoAtom.Terminal.UI uses a single scrolling model across controls: IScrollable + ScrollModel.
This keeps scrollbars, mouse wheel behavior, and nested scrolling consistent.
ScrollViewer provides clipped scrolling for any content visual:
new ScrollViewer(new VStack("Line 1", "Line 2"))If ScrollViewer.Content implements IScrollable, the scroll viewer uses the content’s scroll model:
- scrollbars and mouse wheel update the content scroll offsets
- the content is responsible for exposing its extent and viewport via
ScrollModel
This is how TextArea integrates with ScrollViewer.
If the content is not scrollable, the scroll viewer owns its scroll offsets and scrolls by translating the content viewport.
IScrollable is a simple contract:
public interface IScrollable
{
ScrollModel Scroll { get; }
}ScrollModel represents the state of a scrollable surface:
ViewportWidth/ViewportHeight: visible region size (in cells/rows)ExtentWidth/ExtentHeight: total scrollable size (in cells/rows)OffsetX/OffsetY: current scroll positionVersion: a bindable “snapshot” of the current scroll state
- The scrollable control updates
ScrollModelduringArrange:Scroll.SetViewport(viewportWidth, viewportHeight)Scroll.SetExtent(extentWidth, extentHeight)
ScrollViewerreads the model to decide:- whether scrollbars should be visible,
- the thumb size and range,
- how to clamp offsets.
ScrollModel.Version is a bindable property updated whenever viewport/extent/offset changes.
Controls often mirror it into an internal bindable property in PrepareChildren to avoid “read then write” tracking loops.
See Binding for the pattern.
At a high level:
- Add a
ScrollModelfield:private readonly ScrollModel _scroll; - Implement
IScrollable.Scroll => _scroll; - In
Arrange, update viewport/extent and render content offset byScroll.OffsetX/OffsetY.
Tip
Prefer Scroll.ScrollToMakeVisible(...) when you need “ensure selection visible” behavior.
ScrollBar is an abstract base for scroll bars. Use VScrollBar (vertical) or HScrollBar (horizontal) directly, or let ScrollViewer create and manage them for you.
See also: