diff --git a/src/Avalonia.Controls/VirtualizingStackPanel.cs b/src/Avalonia.Controls/VirtualizingStackPanel.cs index eccada7796..2915ff07d5 100644 --- a/src/Avalonia.Controls/VirtualizingStackPanel.cs +++ b/src/Avalonia.Controls/VirtualizingStackPanel.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Specialized; +using Avalonia.Layout; namespace Avalonia.Controls { @@ -19,8 +20,8 @@ namespace Avalonia.Controls get { return Orientation == Orientation.Horizontal ? - _takenSpace >= Bounds.Width : - _takenSpace >= Bounds.Height; + _takenSpace >= AvailableSpace.Width : + _takenSpace >= AvailableSpace.Height; } } @@ -54,6 +55,9 @@ namespace Avalonia.Controls } } + // TODO: We need to put a reasonable limit on this, probably based on the max window size. + private Size AvailableSpace => ((ILayoutable)this).PreviousMeasure ?? Bounds.Size; + protected override Size ArrangeOverride(Size finalSize) { _canBeRemoved = 0; @@ -99,7 +103,7 @@ namespace Avalonia.Controls rect = new Rect(rect.X, rect.Y - _pixelOffset, rect.Width, rect.Height); child.Arrange(rect); - if (rect.Y >= panelSize.Height) + if (rect.Y >= AvailableSpace.Height) { ++_canBeRemoved; } @@ -116,7 +120,7 @@ namespace Avalonia.Controls rect = new Rect(rect.X - _pixelOffset, rect.Y, rect.Width, rect.Height); child.Arrange(rect); - if (rect.X >= panelSize.Width) + if (rect.X >= AvailableSpace.Width) { ++_canBeRemoved; } @@ -135,7 +139,7 @@ namespace Avalonia.Controls var bounds = Bounds; var gap = Gap; - child.Measure(bounds.Size); + child.Measure(AvailableSpace); ++_averageCount; if (Orientation == Orientation.Vertical) diff --git a/tests/Avalonia.Controls.UnitTests/Avalonia.Controls.UnitTests.csproj b/tests/Avalonia.Controls.UnitTests/Avalonia.Controls.UnitTests.csproj index ec0b19308c..d3a48c02b0 100644 --- a/tests/Avalonia.Controls.UnitTests/Avalonia.Controls.UnitTests.csproj +++ b/tests/Avalonia.Controls.UnitTests/Avalonia.Controls.UnitTests.csproj @@ -143,6 +143,7 @@ + diff --git a/tests/Avalonia.Controls.UnitTests/Presenters/ItemsPresenterTests_Virtualization.cs b/tests/Avalonia.Controls.UnitTests/Presenters/ItemsPresenterTests_Virtualization.cs index 29d32398b4..72ec2e6618 100644 --- a/tests/Avalonia.Controls.UnitTests/Presenters/ItemsPresenterTests_Virtualization.cs +++ b/tests/Avalonia.Controls.UnitTests/Presenters/ItemsPresenterTests_Virtualization.cs @@ -111,6 +111,7 @@ namespace Avalonia.Controls.UnitTests.Presenters Assert.Equal(10, target.Panel.Children.Count); + target.Measure(new Size(120, 120)); target.Arrange(new Rect(0, 0, 100, 120)); Assert.Equal(12, target.Panel.Children.Count); diff --git a/tests/Avalonia.Controls.UnitTests/Presenters/ItemsPresenterTests_Virtualization_Simple.cs b/tests/Avalonia.Controls.UnitTests/Presenters/ItemsPresenterTests_Virtualization_Simple.cs index 09abb85ba7..1c7a08bdb4 100644 --- a/tests/Avalonia.Controls.UnitTests/Presenters/ItemsPresenterTests_Virtualization_Simple.cs +++ b/tests/Avalonia.Controls.UnitTests/Presenters/ItemsPresenterTests_Virtualization_Simple.cs @@ -72,6 +72,7 @@ namespace Avalonia.Controls.UnitTests.Presenters Assert.Equal(10, target.Panel.Children.Count); + target.Measure(new Size(100, 80)); target.Arrange(new Rect(0, 0, 100, 80)); Assert.Equal(8, target.Panel.Children.Count); @@ -90,6 +91,7 @@ namespace Avalonia.Controls.UnitTests.Presenters Assert.Equal(10, target.Panel.Children.Count); ((IScrollable)target).Offset = new Vector(0, 10); + target.Measure(new Size(120, 120)); target.Arrange(new Rect(0, 0, 100, 120)); Assert.Equal(12, target.Panel.Children.Count); diff --git a/tests/Avalonia.Controls.UnitTests/VirtualizingStackPanelTests.cs b/tests/Avalonia.Controls.UnitTests/VirtualizingStackPanelTests.cs new file mode 100644 index 0000000000..900f098198 --- /dev/null +++ b/tests/Avalonia.Controls.UnitTests/VirtualizingStackPanelTests.cs @@ -0,0 +1,52 @@ +// Copyright (c) The Avalonia Project. All rights reserved. +// Licensed under the MIT license. See licence.md file in the project root for full license information. + +using Xunit; + +namespace Avalonia.Controls.UnitTests +{ + public class VirtualizingStackPanelTests + { + public class Vertical + { + [Fact] + public void Reports_IsFull_False_Until_Measure_Height_Is_Reached() + { + var target = (IVirtualizingPanel)new VirtualizingStackPanel(); + + target.Measure(new Size(100, 100)); + target.Arrange(new Rect(target.DesiredSize)); + + Assert.Equal(new Size(0, 0), target.Bounds.Size); + + Assert.False(target.IsFull); + target.Children.Add(new Canvas { Width = 50, Height = 50 }); + Assert.False(target.IsFull); + target.Children.Add(new Canvas { Width = 50, Height = 50 }); + Assert.True(target.IsFull); + } + + [Fact] + public void Reports_Overflow_Only_After_Arrange() + { + var target = (IVirtualizingPanel)new VirtualizingStackPanel(); + + target.Measure(new Size(100, 100)); + target.Arrange(new Rect(target.DesiredSize)); + + Assert.Equal(new Size(0, 0), target.Bounds.Size); + + target.Children.Add(new Canvas { Width = 50, Height = 50 }); + target.Children.Add(new Canvas { Width = 50, Height = 50 }); + target.Children.Add(new Canvas { Width = 50, Height = 50 }); + target.Children.Add(new Canvas { Width = 50, Height = 50 }); + Assert.Equal(0, target.OverflowCount); + + target.Measure(new Size(100, 100)); + target.Arrange(new Rect(target.DesiredSize)); + + Assert.Equal(2, target.OverflowCount); + } + } + } +} \ No newline at end of file