using System; using Avalonia; using Avalonia.Controls; using Avalonia.Controls.Primitives; using Avalonia.Media; using Avalonia.VisualTree; namespace XamlTestApplication { public class TestScrollable : Control, ILogicalScrollable { private int itemCount = 100; private Size _extent; private Vector _offset; private Size _viewport; private Size _lineSize; public bool IsLogicalScrollEnabled => true; public Action InvalidateScroll { get; set; } Size ILogicalScrollable.Extent { get { return _extent; } } Vector ILogicalScrollable.Offset { get { return _offset; } set { _offset = value; InvalidateVisual(); } } Size ILogicalScrollable.Viewport { get { return _viewport; } } public Size ScrollSize { get { return new Size(double.PositiveInfinity, 1); } } public Size PageScrollSize { get { return new Size(double.PositiveInfinity, Bounds.Height); } } public override void Render(DrawingContext context) { var y = 0.0; for (var i = (int)_offset.Y; i < itemCount; ++i) { using (var line = new FormattedText( "Item " + (i + 1), TextBlock.GetFontFamily(this), TextBlock.GetFontSize(this), TextBlock.GetFontStyle(this), TextAlignment.Left, TextBlock.GetFontWeight(this))) { context.DrawText(Brushes.Black, new Point(-_offset.X, y), line); y += _lineSize.Height; } } } public bool BringIntoView(IVisual target, Rect targetRect) { throw new NotImplementedException(); } protected override Size MeasureOverride(Size availableSize) { using (var line = new FormattedText( "Item 100", TextBlock.GetFontFamily(this), TextBlock.GetFontSize(this), TextBlock.GetFontStyle(this), TextAlignment.Left, TextBlock.GetFontWeight(this))) { line.Constraint = availableSize; _lineSize = line.Measure(); return new Size(_lineSize.Width, _lineSize.Height * itemCount); } } protected override Size ArrangeOverride(Size finalSize) { _viewport = new Size(finalSize.Width, finalSize.Height / _lineSize.Height); _extent = new Size(_lineSize.Width, itemCount + 1); InvalidateScroll?.Invoke(); return finalSize; } } }