Browse Source

Recycle elements early when viewport is disjunct.

pull/10892/head
Steven Kirk 3 years ago
parent
commit
9f95bd9156
  1. 11
      src/Avalonia.Controls/VirtualizingStackPanel.cs
  2. 31
      tests/Avalonia.Controls.UnitTests/VirtualizingStackPanelTests.cs

11
src/Avalonia.Controls/VirtualizingStackPanel.cs

@ -166,6 +166,10 @@ namespace Avalonia.Controls
// - Vertical layouts: U = vertical, V = horizontal
var viewport = CalculateMeasureViewport(items);
// If the viewport is disjunct then we can recycle everything.
if (viewport.viewportIsDisjunct)
_realizedElements.RecycleAllElements(_recycleElement);
// Do the measure, creating/recycling elements as necessary to fill the viewport. Don't
// write to _realizedElements yet, only _measureElements.
RealizeElements(items, availableSize, ref viewport);
@ -409,6 +413,7 @@ namespace Avalonia.Controls
var viewportStart = Orientation == Orientation.Horizontal ? viewport.X : viewport.Y;
var viewportEnd = Orientation == Orientation.Horizontal ? viewport.Right : viewport.Bottom;
// Get or estimate the anchor element from which to start realization.
var itemCount = items?.Count ?? 0;
var (anchorIndex, anchorU) = _realizedElements.GetOrEstimateAnchorElementForViewport(
viewportStart,
@ -416,12 +421,17 @@ namespace Avalonia.Controls
itemCount,
ref _lastEstimatedElementSizeU);
// Check if the anchor element is not within the currently realized elements.
var disjunct = anchorIndex < _realizedElements.FirstIndex ||
anchorIndex > _realizedElements.LastIndex;
return new MeasureViewport
{
anchorIndex = anchorIndex,
anchorU = anchorU,
viewportUStart = viewportStart,
viewportUEnd = viewportEnd,
viewportIsDisjunct = disjunct,
};
}
@ -895,6 +905,7 @@ namespace Avalonia.Controls
public double measuredV;
public double realizedEndU;
public int lastIndex;
public bool viewportIsDisjunct;
}
}
}

31
tests/Avalonia.Controls.UnitTests/VirtualizingStackPanelTests.cs

@ -83,7 +83,7 @@ namespace Avalonia.Controls.UnitTests
}
[Fact]
public void Scrolls_To_Index()
public void Scrolls_Down_To_Index()
{
using var app = App();
var (target, scroll, itemsControl) = CreateTarget();
@ -93,6 +93,35 @@ namespace Avalonia.Controls.UnitTests
AssertRealizedItems(target, itemsControl, 11, 10);
}
[Fact]
public void Scrolls_Up_To_Index()
{
using var app = App();
var (target, scroll, itemsControl) = CreateTarget();
scroll.ScrollToEnd();
Layout(target);
Assert.Equal(90, target.FirstRealizedIndex);
target.ScrollIntoView(20);
AssertRealizedItems(target, itemsControl, 20, 10);
}
[Fact]
public void Scrolling_Up_To_Index_Does_Not_Create_A_Page_Of_Unrealized_Elements()
{
using var app = App();
var (target, scroll, itemsControl) = CreateTarget();
scroll.ScrollToEnd();
Layout(target);
target.ScrollIntoView(20);
Assert.Equal(11, target.Children.Count);
}
[Fact]
public void Creates_Elements_On_Item_Insert_1()
{

Loading…
Cancel
Save