ScrollViewer PatternPrimary APIs:
ScrollViewerIScrollAnchorProviderScrollChangedEventArgsScrollBarVisibilitySnapPointsTypeSnapPointsAlignmentImportant properties/events/methods:
ScrollViewer.OffsetScrollViewer.ExtentScrollViewer.ViewportScrollViewer.ScrollBarMaximumScrollViewer.ScrollChangedLineUp(), LineDown(), LineLeft(), LineRight()PageUp(), PageDown(), PageLeft(), PageRight()ScrollToHome(), ScrollToEnd()RegisterAnchorCandidate(Control)UnregisterAnchorCandidate(Control)Attached property surface:
ScrollViewer.BringIntoViewOnFocusChangeScrollViewer.HorizontalScrollBarVisibilityScrollViewer.VerticalScrollBarVisibilityScrollViewer.HorizontalSnapPointsTypeScrollViewer.VerticalSnapPointsTypeScrollViewer.HorizontalSnapPointsAlignmentScrollViewer.VerticalSnapPointsAlignmentScrollViewer.AllowAutoHideScrollViewer.IsScrollChainingEnabledScrollViewer.IsScrollInertiaEnabledScrollViewer.IsDeferredScrollingEnabledReference source files:
src/Avalonia.Controls/ScrollViewer.cssrc/Avalonia.Controls/ScrollChangedEventArgs.csScrollViewer Pattern<ScrollViewer xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
HorizontalScrollBarVisibility="Auto"
VerticalScrollBarVisibility="Auto"
AllowAutoHide="True">
<StackPanel Spacing="8" Margin="12">
<TextBlock Text="Scrollable content" FontWeight="Bold" />
<Border Height="800" Background="#102060" />
</StackPanel>
</ScrollViewer>
Use this as the default when content size can exceed layout bounds.
Offset is the current scroll position (Vector) in content coordinates.Extent is the total scrollable content size.Viewport is the currently visible content size.ScrollBarMaximum is computed from Extent - Viewport and clamps to non-negative values.Pattern:
using Avalonia;
using Avalonia.Controls;
void RestorePosition(ScrollViewer viewer, Vector savedOffset)
{
viewer.Offset = savedOffset;
}
Vector CapturePosition(ScrollViewer viewer) => viewer.Offset;
ScrollViewer exposes imperative movement methods:
LineUp, LineDown, LineLeft, LineRightPageUp, PageDown, PageLeft, PageRightScrollToHome, ScrollToEndvoid ScrollOnePageDown(ScrollViewer viewer)
{
viewer.PageDown();
}
void JumpToTop(ScrollViewer viewer)
{
viewer.ScrollToHome();
}
These methods use SetCurrentValue internally and preserve binding relationships on Offset.
You can tune scrolling behavior directly in XAML:
<ItemsControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
ScrollViewer.VerticalScrollBarVisibility="Auto"
ScrollViewer.IsScrollChainingEnabled="True"
ScrollViewer.IsScrollInertiaEnabled="True"
ScrollViewer.IsDeferredScrollingEnabled="False"
ScrollViewer.AllowAutoHide="True" />
Guidance:
Snap points are controlled with attached properties:
<ItemsControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
ScrollViewer.HorizontalSnapPointsType="None"
ScrollViewer.VerticalSnapPointsType="MandatorySingle"
ScrollViewer.VerticalSnapPointsAlignment="Near" />
For dynamic content where insertion/removal should preserve visible context, ScrollViewer also supports anchoring via IScrollAnchorProvider (CurrentAnchor, RegisterAnchorCandidate, UnregisterAnchorCandidate). This is primarily useful in custom controls/presenters.
BringIntoViewOnFocusChange determines whether focus transitions auto-scroll focused elements into view.
<ScrollViewer xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
BringIntoViewOnFocusChange="True">
<StackPanel>
<TextBox Width="240" Margin="0,0,0,500" />
<TextBox Width="240" />
</StackPanel>
</ScrollViewer>
This is generally desirable for keyboard navigation and accessibility.
Observe scroll changes:
using Avalonia.Controls;
void AttachScrollLogging(ScrollViewer viewer)
{
viewer.ScrollChanged += (_, e) =>
{
// e.OffsetDelta, e.ExtentDelta, and e.ViewportDelta are useful for diagnostics.
_ = e.Offset;
};
}
Restore last position after loading:
using Avalonia;
using Avalonia.Controls;
void RestoreAfterLoad(ScrollViewer viewer, Vector previousOffset)
{
viewer.Offset = previousOffset;
}
Offset for navigation-heavy views.BringIntoViewOnFocusChange enabled unless you intentionally own focus scrolling.ScrollChanged for diagnostics and state sync, not heavy compute work.Disabled.Offset on every collection change.BringIntoViewOnFocusChange on the effective ScrollViewer.IsScrollChainingEnabled and IsScrollInertiaEnabled on parent/child surfaces.Offset breaks after imperative scroll calls.
LineDown, PageDown, etc.) or SetCurrentValue-equivalent flows.