Skip to content

Commit 3515b99

Browse files
authored
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
1 parent d43dde5 commit 3515b99

File tree

2 files changed

+64
-0
lines changed

2 files changed

+64
-0
lines changed

src/Avalonia.Controls/VirtualizingStackPanel.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,8 @@ public class VirtualizingStackPanel : VirtualizingPanel, IScrollSnapPointsInfo
7272
private Dictionary<object, Stack<Control>>? _recyclePool;
7373
private Control? _focusedElement;
7474
private int _focusedIndex = -1;
75+
private Control? _realizingElement;
76+
private int _realizingIndex = -1;
7577

7678
public VirtualizingStackPanel()
7779
{
@@ -336,6 +338,8 @@ protected override void OnItemsChanged(IReadOnlyList<object?> items, NotifyColle
336338
return _scrollToElement;
337339
if (_focusedIndex == index)
338340
return _focusedElement;
341+
if (index == _realizingIndex)
342+
return _realizingElement;
339343
if (GetRealizedElement(index) is { } realized)
340344
return realized;
341345
if (Items[index] is Control c && c.GetValue(RecycleKeyProperty) == s_itemIsItsOwnContainer)
@@ -349,6 +353,8 @@ protected internal override int IndexFromContainer(Control container)
349353
return _scrollToIndex;
350354
if (container == _focusedElement)
351355
return _focusedIndex;
356+
if (container == _realizingElement)
357+
return _realizingIndex;
352358
return _realizedElements?.GetIndex(container) ?? -1;
353359
}
354360

@@ -532,7 +538,9 @@ private void RealizeElements(
532538
// Start at the anchor element and move forwards, realizing elements.
533539
do
534540
{
541+
_realizingIndex = index;
535542
var e = GetOrCreateElement(items, index);
543+
_realizingElement = e;
536544
e.Measure(availableSize);
537545

538546
var sizeU = horizontal ? e.DesiredSize.Width : e.DesiredSize.Height;
@@ -543,6 +551,8 @@ private void RealizeElements(
543551

544552
u += sizeU;
545553
++index;
554+
_realizingIndex = -1;
555+
_realizingElement = null;
546556
} while (u < viewport.viewportUEnd && index < items.Count);
547557

548558
// Store the last index and end U position for the desired size calculation.

tests/Avalonia.Controls.UnitTests/VirtualizingStackPanelTests.cs

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -501,6 +501,33 @@ public void NthChild_Selector_Works()
501501
}
502502
}
503503

504+
// https://github.com/AvaloniaUI/Avalonia/issues/12838
505+
[Fact]
506+
public void NthChild_Selector_Works_For_ItemTemplate_Children()
507+
{
508+
using var app = App();
509+
510+
var style = new Style(x => x.OfType<ContentPresenter>().NthChild(5, 0).Child().OfType<Canvas>())
511+
{
512+
Setters = { new Setter(Panel.BackgroundProperty, Brushes.Red) },
513+
};
514+
515+
var (target, _, _) = CreateTarget(styles: new[] { style });
516+
var realized = target.GetRealizedContainers()!.Cast<ContentPresenter>().ToList();
517+
518+
Assert.Equal(10, realized.Count);
519+
520+
for (var i = 0; i < 10; ++i)
521+
{
522+
var container = realized[i];
523+
var index = target.IndexFromContainer(container);
524+
var expectedBackground = (i == 4 || i == 9) ? Brushes.Red : null;
525+
526+
Assert.Equal(i, index);
527+
Assert.Equal(expectedBackground, ((Canvas) container.Child!).Background);
528+
}
529+
}
530+
504531
[Fact]
505532
public void NthLastChild_Selector_Works()
506533
{
@@ -527,6 +554,33 @@ public void NthLastChild_Selector_Works()
527554
}
528555
}
529556

557+
// https://github.com/AvaloniaUI/Avalonia/issues/12838
558+
[Fact]
559+
public void NthLastChild_Selector_Works_For_ItemTemplate_Children()
560+
{
561+
using var app = App();
562+
563+
var style = new Style(x => x.OfType<ContentPresenter>().NthLastChild(5, 0).Child().OfType<Canvas>())
564+
{
565+
Setters = { new Setter(Panel.BackgroundProperty, Brushes.Red) },
566+
};
567+
568+
var (target, _, _) = CreateTarget(styles: new[] { style });
569+
var realized = target.GetRealizedContainers()!.Cast<ContentPresenter>().ToList();
570+
571+
Assert.Equal(10, realized.Count);
572+
573+
for (var i = 0; i < 10; ++i)
574+
{
575+
var container = realized[i];
576+
var index = target.IndexFromContainer(container);
577+
var expectedBackground = (i == 0 || i == 5) ? Brushes.Red : null;
578+
579+
Assert.Equal(i, index);
580+
Assert.Equal(expectedBackground, ((Canvas) container.Child!).Background);
581+
}
582+
}
583+
530584
[Fact]
531585
public void ContainerPrepared_Is_Raised_When_Scrolling()
532586
{

0 commit comments

Comments
 (0)