From ce2cd52964cf247d7e9d645995fd2c4e677737d7 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Thu, 9 Mar 2023 16:24:13 +0100 Subject: [PATCH] Add lifecycle event tests with virtualization. And fix index error in VirtualizingStackPanel. --- .../VirtualizingStackPanel.cs | 2 +- .../ListBoxTests.cs | 140 ++++++++++++++++++ 2 files changed, 141 insertions(+), 1 deletion(-) diff --git a/src/Avalonia.Controls/VirtualizingStackPanel.cs b/src/Avalonia.Controls/VirtualizingStackPanel.cs index 4970a333a5..977f8a1e8c 100644 --- a/src/Avalonia.Controls/VirtualizingStackPanel.cs +++ b/src/Avalonia.Controls/VirtualizingStackPanel.cs @@ -1078,7 +1078,7 @@ namespace Avalonia.Controls // elements after the insertion point. var elementCount = _elements.Count; var start = Math.Max(realizedIndex, 0); - var newIndex = first + count; + var newIndex = realizedIndex + count; for (var i = start; i < elementCount; ++i) { diff --git a/tests/Avalonia.Controls.UnitTests/ListBoxTests.cs b/tests/Avalonia.Controls.UnitTests/ListBoxTests.cs index d2b75a81ca..72476e34e9 100644 --- a/tests/Avalonia.Controls.UnitTests/ListBoxTests.cs +++ b/tests/Avalonia.Controls.UnitTests/ListBoxTests.cs @@ -785,6 +785,146 @@ namespace Avalonia.Controls.UnitTests } } + [Fact] + public void ContainerPrepared_Is_Called_For_Each_Item_Container_On_Layout() + { + using var app = UnitTestApplication.Start(TestServices.MockPlatformRenderInterface); + + var target = new ListBox + { + Template = ListBoxTemplate(), + Items = { "Foo", "Bar", "Baz" }, + }; + + var result = new List(); + var index = 0; + + target.ContainerPrepared += (s, e) => + { + Assert.Equal(index++, e.Index); + result.Add(e.Container); + }; + + Prepare(target); + + Assert.Equal(3, result.Count); + Assert.Equal(target.GetRealizedContainers(), result); + } + + [Fact] + public void ContainerPrepared_Is_Called_For_Each_ItemsSource_Container_On_Layout() + { + using var app = UnitTestApplication.Start(TestServices.MockPlatformRenderInterface); + + var target = new ListBox + { + Template = ListBoxTemplate(), + ItemsSource = new[] { "Foo", "Bar", "Baz" }, + }; + + var result = new List(); + var index = 0; + + target.ContainerPrepared += (s, e) => + { + Assert.Equal(index++, e.Index); + result.Add(e.Container); + }; + + Prepare(target); + + Assert.Equal(3, result.Count); + Assert.Equal(target.GetRealizedContainers(), result); + } + + [Fact] + public void ContainerPrepared_Is_Called_For_Added_Item() + { + using var app = UnitTestApplication.Start(TestServices.MockPlatformRenderInterface); + + var data = new AvaloniaList { "Foo", "Bar", "Baz" }; + var target = new ListBox + { + Template = ListBoxTemplate(), + ItemsSource = data, + }; + + Prepare(target); + + var result = new List(); + + target.ContainerPrepared += (s, e) => + { + Assert.Equal(3, e.Index); + result.Add(e.Container); + }; + + data.Add("Qux"); + Layout(target); + + Assert.Equal(1, result.Count); + } + + [Fact] + public void ContainerIndexChanged_Is_Called_When_Item_Added() + { + using var app = UnitTestApplication.Start(TestServices.MockPlatformRenderInterface); + + var data = new AvaloniaList { "Foo", "Bar", "Baz" }; + var target = new ListBox + { + Template = ListBoxTemplate(), + ItemsSource = data, + }; + + Prepare(target); + + var result = new List(); + var index = 1; + + target.ContainerIndexChanged += (s, e) => + { + Assert.Equal(index++, e.OldIndex); + Assert.Equal(index, e.NewIndex); + result.Add(e.Container); + }; + + data.Insert(1, "Qux"); + Layout(target); + + Assert.Equal(2, result.Count); + Assert.Equal(target.GetRealizedContainers().Skip(2), result); + } + + [Fact] + public void ContainerClearing_Is_Called_When_Item_Removed() + { + using var app = UnitTestApplication.Start(TestServices.MockPlatformRenderInterface); + + var data = new AvaloniaList { "Foo", "Bar", "Baz" }; + var target = new ListBox + { + Template = ListBoxTemplate(), + ItemsSource = data, + }; + + Prepare(target); + + var expected = target.ContainerFromIndex(1); + var raised = 0; + + target.ContainerClearing += (s, e) => + { + Assert.Same(expected, e.Container); + ++raised; + }; + + data.RemoveAt(1); + Layout(target); + + Assert.Equal(1, raised); + } + private class ResettingCollection : List, INotifyCollectionChanged { public ResettingCollection(int itemCount)