From 926a0025c0d83dcfc6bcea4daa3fed50b5ef2788 Mon Sep 17 00:00:00 2001 From: Mike Corsaro Date: Wed, 22 Nov 2023 14:20:41 -0800 Subject: [PATCH] [Windows] Address CollectionView virtualization (#18813) * Add hard value for height w/ ItemContent control to partially allow virtualization to work * Update test to be more robust * Add real-width for ItemContentControl --------- Co-authored-by: Mike Corsaro --- .../CollectionView/ItemContentControl.cs | 6 ++ .../CollectionViewTests.Windows.cs | 61 +++++++++++++++++++ 2 files changed, 67 insertions(+) diff --git a/src/Controls/src/Core/Platform/Windows/CollectionView/ItemContentControl.cs b/src/Controls/src/Core/Platform/Windows/CollectionView/ItemContentControl.cs index 22a4449f7c86..4be1e9dedf38 100644 --- a/src/Controls/src/Core/Platform/Windows/CollectionView/ItemContentControl.cs +++ b/src/Controls/src/Core/Platform/Windows/CollectionView/ItemContentControl.cs @@ -284,6 +284,12 @@ protected override WSize MeasureOverride(WSize availableSize) { if (_renderer == null) { + // Make sure we supply a real number for sizes otherwise virtualization won't function + if (double.IsFinite(availableSize.Width) && !double.IsFinite(availableSize.Height)) + return new WSize(availableSize.Width, 32); + else if (!double.IsFinite(availableSize.Width) && double.IsFinite(availableSize.Height)) + return new WSize(88, availableSize.Height); + return base.MeasureOverride(availableSize); } diff --git a/src/Controls/tests/DeviceTests/Elements/CollectionView/CollectionViewTests.Windows.cs b/src/Controls/tests/DeviceTests/Elements/CollectionView/CollectionViewTests.Windows.cs index a4eb1e2f914f..cedafb04aa28 100644 --- a/src/Controls/tests/DeviceTests/Elements/CollectionView/CollectionViewTests.Windows.cs +++ b/src/Controls/tests/DeviceTests/Elements/CollectionView/CollectionViewTests.Windows.cs @@ -4,6 +4,7 @@ using Microsoft.Maui.Controls; using Microsoft.Maui.Controls.Handlers.Items; using Microsoft.Maui.Handlers; +using Microsoft.Maui.Platform; using Microsoft.UI.Xaml; using Xunit; using WSetter = Microsoft.UI.Xaml.Setter; @@ -101,6 +102,66 @@ void ValidateItemContainerStyle(CollectionView collectionView) Assert.Equal(0d, minHeight); } + [Fact] + public async Task ValidateItemsVirtualize() + { + SetupBuilder(); + + const int listItemCount = 1000; + + var collectionView = new CollectionView() + { + ItemTemplate = new Controls.DataTemplate(() => + { + var template = new Grid() + { + ColumnDefinitions = new ColumnDefinitionCollection( + [ + new ColumnDefinition(25), + new ColumnDefinition(25), + new ColumnDefinition(25), + new ColumnDefinition(25), + new ColumnDefinition(25), + ]) + }; + + for (int i = 0; i < 5; i++) + { + var label = new Label(); + label.SetBinding(Label.TextProperty, new Binding("Symbol")); + Grid.SetColumn(label, i); + template.Add(label); + } + + return template; + }), + ItemsSource = Enumerable.Range(0, listItemCount) + .Select(x => new { Symbol = x }) + .ToList() + }; + + await CreateHandlerAndAddToWindow(collectionView, async handler => + { + var listView = (UI.Xaml.Controls.ListView)collectionView.Handler.PlatformView; + + int childCount = 0; + int prevChildCount = -1; + + await Task.Delay(2000); + + await AssertionExtensions.Wait(() => + { + // Wait until the list stops growing + prevChildCount = childCount; + childCount = listView.GetChildren().Count(); + return childCount == prevChildCount; + }, 10000); + + // If this is broken we'll get way more than 1000 elements + Assert.True(childCount < 1000); + }); + } + [Fact] public async Task ValidateSendRemainingItemsThresholdReached() {