Browse Source

Fix VirtualizingStackPanel and nth-child for the currently realizing item container (#12957)

* Added failing tests for VirtualizingStackPanel and nth-child

* VirtualizingStackPanel: support index of currently realizing item
release/11.0.5-rc1
Julien Lebosquain 2 years ago
committed by Steven Kirk
parent
commit
2722f9bcfd
  1. 10
      src/Avalonia.Controls/VirtualizingStackPanel.cs
  2. 54
      tests/Avalonia.Controls.UnitTests/VirtualizingStackPanelTests.cs

10
src/Avalonia.Controls/VirtualizingStackPanel.cs

@ -72,6 +72,8 @@ namespace Avalonia.Controls
private Dictionary<object, Stack<Control>>? _recyclePool;
private Control? _focusedElement;
private int _focusedIndex = -1;
private Control? _realizingElement;
private int _realizingIndex = -1;
public VirtualizingStackPanel()
{
@ -336,6 +338,8 @@ namespace Avalonia.Controls
return _scrollToElement;
if (_focusedIndex == index)
return _focusedElement;
if (index == _realizingIndex)
return _realizingElement;
if (GetRealizedElement(index) is { } realized)
return realized;
if (Items[index] is Control c && c.GetValue(RecycleKeyProperty) == s_itemIsItsOwnContainer)
@ -349,6 +353,8 @@ namespace Avalonia.Controls
return _scrollToIndex;
if (container == _focusedElement)
return _focusedIndex;
if (container == _realizingElement)
return _realizingIndex;
return _realizedElements?.GetIndex(container) ?? -1;
}
@ -532,7 +538,9 @@ namespace Avalonia.Controls
// Start at the anchor element and move forwards, realizing elements.
do
{
_realizingIndex = index;
var e = GetOrCreateElement(items, index);
_realizingElement = e;
e.Measure(availableSize);
var sizeU = horizontal ? e.DesiredSize.Width : e.DesiredSize.Height;
@ -543,6 +551,8 @@ namespace Avalonia.Controls
u += sizeU;
++index;
_realizingIndex = -1;
_realizingElement = null;
} while (u < viewport.viewportUEnd && index < items.Count);
// Store the last index and end U position for the desired size calculation.

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

@ -501,6 +501,33 @@ namespace Avalonia.Controls.UnitTests
}
}
// https://github.com/AvaloniaUI/Avalonia/issues/12838
[Fact]
public void NthChild_Selector_Works_For_ItemTemplate_Children()
{
using var app = App();
var style = new Style(x => x.OfType<ContentPresenter>().NthChild(5, 0).Child().OfType<Canvas>())
{
Setters = { new Setter(Panel.BackgroundProperty, Brushes.Red) },
};
var (target, _, _) = CreateTarget(styles: new[] { style });
var realized = target.GetRealizedContainers()!.Cast<ContentPresenter>().ToList();
Assert.Equal(10, realized.Count);
for (var i = 0; i < 10; ++i)
{
var container = realized[i];
var index = target.IndexFromContainer(container);
var expectedBackground = (i == 4 || i == 9) ? Brushes.Red : null;
Assert.Equal(i, index);
Assert.Equal(expectedBackground, ((Canvas) container.Child!).Background);
}
}
[Fact]
public void NthLastChild_Selector_Works()
{
@ -527,6 +554,33 @@ namespace Avalonia.Controls.UnitTests
}
}
// https://github.com/AvaloniaUI/Avalonia/issues/12838
[Fact]
public void NthLastChild_Selector_Works_For_ItemTemplate_Children()
{
using var app = App();
var style = new Style(x => x.OfType<ContentPresenter>().NthLastChild(5, 0).Child().OfType<Canvas>())
{
Setters = { new Setter(Panel.BackgroundProperty, Brushes.Red) },
};
var (target, _, _) = CreateTarget(styles: new[] { style });
var realized = target.GetRealizedContainers()!.Cast<ContentPresenter>().ToList();
Assert.Equal(10, realized.Count);
for (var i = 0; i < 10; ++i)
{
var container = realized[i];
var index = target.IndexFromContainer(container);
var expectedBackground = (i == 0 || i == 5) ? Brushes.Red : null;
Assert.Equal(i, index);
Assert.Equal(expectedBackground, ((Canvas) container.Child!).Background);
}
}
[Fact]
public void ContainerPrepared_Is_Raised_When_Scrolling()
{

Loading…
Cancel
Save