Table of Contents

Class ScrollViewer

Namespace
Icy.UI.Controls
Assembly
IcyUI.dll

Clips Content to this control's bounds and lets it be scrolled within that viewport via HorizontalOffset/VerticalOffset - settable directly, or driven by the mouse wheel/touch-swipe (see IScrollEvents).

public class ScrollViewer : ContentControl, INotifyPropertyChanging, IBindingTarget, INotifyPropertyChanged, INotifyFocusChanged, IContainerLayout
Inheritance
ScrollViewer
Implements
Inherited Members
Extension Methods

Remarks

No visible scrollbar thumbs are drawn in v1 - this is purely the viewport/offset/clipping model. A visual scrollbar can be layered on top later using ExtentWidth/ExtentHeight/ ViewportWidth/ViewportHeight to size a thumb.

Constructors

ScrollViewer()

Initializes a new instance of the ScrollViewer class.

public ScrollViewer()

Properties

ExtentHeight

Gets Content's full natural height, regardless of how much of it is currently visible - or, when Content implements IVirtualizingScrollInfo, its own reported estimate instead of a full measure.

public float ExtentHeight { get; }

Property Value

float

Remarks

While VerticalScrollMode is Disabled, the extent is capped at ViewportHeight, so there is nothing to scroll vertically.

ExtentWidth

Gets Content's full natural width, regardless of how much of it is currently visible - or, when Content implements IVirtualizingScrollInfo, its own reported estimate instead of a full measure.

public float ExtentWidth { get; }

Property Value

float

Remarks

While HorizontalScrollMode is Disabled, the extent is capped at ViewportWidth, so there is nothing to scroll horizontally.

HorizontalOffset

Gets or sets how far Content is scrolled horizontally, clamped to [0, ExtentWidth - ViewportWidth].

[BindingOverride(BindingMode.TwoWay)]
public float HorizontalOffset { get; set; }

Property Value

float

HorizontalScrollMode

Gets or sets whether Content scrolls horizontally. Defaults to Enabled.

public ScrollMode HorizontalScrollMode { get; set; }

Property Value

ScrollMode

Remarks

  • Enabled: the content keeps its natural width, which can be wider than the viewport.
  • Disabled: the content is laid out at most as wide as the viewport, and HorizontalOffset stays at 0. Use it for pages that should only scroll vertically, so a long line of text can't widen the whole page.

PanningDeceleration

Gets or sets how quickly a fling slows down, in this control's units per second squared. Defaults to 1500; 0 disables inertia.

public float PanningDeceleration { get; set; }

Property Value

float

Exceptions

ArgumentOutOfRangeException

The value is negative or not finite.

PanningMode

Gets or sets the axes this ScrollViewer pans along with touch and the middle mouse button. Defaults to Auto.

public PanningMode PanningMode { get; set; }

Property Value

PanningMode

Remarks

A pan claims a drag only along axes where the content can still move in the drag's direction, so a list that is already at its edge lets the gesture reach the next scroll area out. The left mouse button never pans.

VerticalOffset

Gets or sets how far Content is scrolled vertically, clamped to [0, ExtentHeight - ViewportHeight].

[BindingOverride(BindingMode.TwoWay)]
public float VerticalOffset { get; set; }

Property Value

float

VerticalScrollMode

Gets or sets whether Content scrolls vertically. Defaults to Enabled.

public ScrollMode VerticalScrollMode { get; set; }

Property Value

ScrollMode

Remarks

  • Enabled: the content keeps its natural height, which can be taller than the viewport.
  • Disabled: the content is laid out at most as tall as the viewport, and VerticalOffset stays at 0. Use it for content that should only scroll horizontally.

ViewportHeight

Gets the visible viewport's height, i.e. this control's ContentBounds height (already inset by BorderThickness and Padding).

public float ViewportHeight { get; }

Property Value

float

ViewportWidth

Gets the visible viewport's width, i.e. this control's ContentBounds width (already inset by BorderThickness and Padding).

public float ViewportWidth { get; }

Property Value

float

Methods

ArrangeContent()

Handles custom arrange logic when overridden in any UIElement instance.

protected override void ArrangeContent()

Remarks

This method is called during the arrange pass to position and size the element's content within its final bounds. The element's position and size are already determined by the layout system and available in the ActualBounds property.

When implementing this method:

  • Position child elements within the available space;
  • Respect the element's padding when positioning content;
  • Handle any content-specific layout requirements;
  • Call Arrange() on child elements if needed.

CanHitTestChildren()

Gets a value indicating whether HitTest(Vector2) descends into this element's children.

protected override bool CanHitTestChildren()

Returns

bool

true by default. Returning false makes the element itself the hit target for every point inside it - e.g. a scrolling list during a fling, so the press that stops it doesn't reach an item.

GetDragAxes(in DragClaimContext)

Returns the axes along which this element wants to own a drag that starts on it or a descendant.

protected override DragAxes GetDragAxes(in DragClaimContext context)

Parameters

context DragClaimContext

The starting drag.

Returns

DragAxes

The claimed axes; the base implementation returns None.

Remarks

When a drag starts, Canvas asks the hit element and each ancestor in turn. The innermost element whose answer contains the drag's main axis (the larger component of LocalDirection) owns the gesture. If none does, the innermost element with any answer owns it. Only the owner receives OnDragStarted(Point), OnDragPerforming(Point), OnDragFling(Vector2) and OnDragEnded(Point).

An element that handles drags must override this method: overriding OnDragStarted(Point) alone receives nothing.

OnDetached()

Raises the Detached event.

protected override void OnDetached()

Remarks

Propagates null to every element in GetVisualChildren(), mirroring OnAttached() - see its remarks.

OnDragEnded(Point)

Invoked by Canvas when a drag sequence owned by this element (see GetDragAxes(in DragClaimContext)) has ended - released or canceled. The base implementation does nothing.

protected override void OnDragEnded(Point screenPoint)

Parameters

screenPoint Point

The drag's ending position, in screen/window space.

OnDragFling(Vector2)

Invoked by Canvas on the owner of a drag that completed (was released), right before OnDragEnded(Point). It isn't invoked when the drag is canceled. The base implementation does nothing.

protected override void OnDragFling(Vector2 screenVelocity)

Parameters

screenVelocity Vector2

The release velocity, in physical pixels per second.

OnDragPerforming(Point)

Invoked by Canvas whenever the pointer moves during a drag sequence owned by this element (see GetDragAxes(in DragClaimContext)). The base implementation does nothing.

protected override void OnDragPerforming(Point screenPoint)

Parameters

screenPoint Point

The drag's current position, in screen/window space.

OnDragStarted(Point)

Invoked by Canvas when a drag sequence starts and this element owns it (see GetDragAxes(in DragClaimContext); overriding this method alone receives nothing). The base implementation does nothing.

protected override void OnDragStarted(Point screenPoint)

Parameters

screenPoint Point

The drag's starting position, in screen/window space.

OnScroll(ScrollInfo)

Invoked by Canvas when the mouse wheel/touch-swipe scrolls (see Scroll) while this element (or a descendant) is hovered. The base implementation does nothing and returns false.

protected override bool OnScroll(ScrollInfo info)

Parameters

info ScrollInfo

The scroll delta and axis.

Returns

bool

true if this element actually consumed the scroll (e.g. a ScrollViewer that had room left to scroll further in info's direction) - Canvas stops dispatching to further ancestors once an element returns true, so one nested scrollable region doesn't also scroll every scrollable ancestor around it. Returning false (e.g. already scrolled to the limit in that direction) lets the event bubble up to an outer scrollable ancestor, which is what makes "overscroll" naturally hand off to it.

StopInertia()

Stops a running fling immediately, leaving the offsets where they are.

public void StopInertia()

Events

ScrollChanged

Occurs when HorizontalOffset or VerticalOffset changes.

public event EventHandler? ScrollChanged

Event Type

EventHandler