diff --git a/src/Avalonia.Controls/Presenters/ItemVirtualizerSimple.cs b/src/Avalonia.Controls/Presenters/ItemVirtualizerSimple.cs index 7e7778a3fa..27a29a1e04 100644 --- a/src/Avalonia.Controls/Presenters/ItemVirtualizerSimple.cs +++ b/src/Avalonia.Controls/Presenters/ItemVirtualizerSimple.cs @@ -105,6 +105,8 @@ namespace Avalonia.Controls.Presenters { base.ItemsChanged(items, e); + var panel = VirtualizingPanel; + if (items != null) { switch (e.Action) @@ -147,6 +149,14 @@ namespace Avalonia.Controls.Presenters FirstIndex = NextIndex = 0; } + // If we are scrolled to view a partially visible last item but controls were added + // then we need to return to a non-offset scroll position. + if (panel.PixelOffset != 0 && FirstIndex + panel.Children.Count < ItemCount) + { + panel.PixelOffset = 0; + RecycleContainersForMove(1); + } + InvalidateScroll(); } diff --git a/tests/Avalonia.Controls.UnitTests/Presenters/ItemsPresenterTests_Virtualization_Simple.cs b/tests/Avalonia.Controls.UnitTests/Presenters/ItemsPresenterTests_Virtualization_Simple.cs index e3614e152b..aa02ecb666 100644 --- a/tests/Avalonia.Controls.UnitTests/Presenters/ItemsPresenterTests_Virtualization_Simple.cs +++ b/tests/Avalonia.Controls.UnitTests/Presenters/ItemsPresenterTests_Virtualization_Simple.cs @@ -456,6 +456,32 @@ namespace Avalonia.Controls.UnitTests.Presenters Assert.Equal(expected, actual); } + [Fact] + public void Scrolling_To_Partial_Last_Item_Then_Adding_Item_Updates_Containers() + { + var target = CreateTarget(itemCount: 10); + var items = (IList)target.Items; + + target.ApplyTemplate(); + target.Measure(new Size(100, 95)); + target.Arrange(new Rect(0, 0, 100, 95)); + + ((ILogicalScrollable)target).Offset = new Vector(0, 1); + Assert.Equal(new Vector(0, 1), ((ILogicalScrollable)target).Offset); + + var expected = Enumerable.Range(0, 10).Select(x => $"Item {x}").ToList(); + var actual = target.Panel.Children.Select(x => x.DataContext).ToList(); + Assert.Equal(expected, actual); + Assert.Equal(10, ((IVirtualizingPanel)target.Panel).PixelOffset); + + items.Add("Item 10"); + + expected = Enumerable.Range(1, 10).Select(x => $"Item {x}").ToList(); + actual = target.Panel.Children.Select(x => x.DataContext).ToList(); + Assert.Equal(expected, actual); + Assert.Equal(0, ((IVirtualizingPanel)target.Panel).PixelOffset); + } + public class Vertical { [Fact]