|
|
|
@ -646,7 +646,7 @@ namespace Avalonia.Controls.UnitTests |
|
|
|
{ |
|
|
|
// Issue #11272
|
|
|
|
using var app = App(); |
|
|
|
var (_, _, itemsControl) = CreateUnrootedTarget(); |
|
|
|
var (_, _, itemsControl) = CreateUnrootedTarget<ItemsControl>(); |
|
|
|
var container = new Decorator { Margin = new Thickness(100) }; |
|
|
|
var root = new TestRoot(true, container); |
|
|
|
|
|
|
|
@ -657,6 +657,44 @@ namespace Avalonia.Controls.UnitTests |
|
|
|
root.LayoutManager.ExecuteLayoutPass(); |
|
|
|
} |
|
|
|
|
|
|
|
[Fact] |
|
|
|
public void Supports_Null_Recycle_Key_When_Scrolling() |
|
|
|
{ |
|
|
|
using var app = App(); |
|
|
|
var (_, scroll, itemsControl) = CreateUnrootedTarget<NonRecyclingItemsControl>(); |
|
|
|
var root = CreateRoot(itemsControl); |
|
|
|
|
|
|
|
root.LayoutManager.ExecuteInitialLayoutPass(); |
|
|
|
|
|
|
|
var firstItem = itemsControl.ContainerFromIndex(0)!; |
|
|
|
scroll.Offset = new(0, 20); |
|
|
|
|
|
|
|
Layout(itemsControl); |
|
|
|
|
|
|
|
Assert.Null(firstItem.Parent); |
|
|
|
Assert.Null(firstItem.VisualParent); |
|
|
|
Assert.DoesNotContain(firstItem, itemsControl.ItemsPanelRoot!.Children); |
|
|
|
} |
|
|
|
|
|
|
|
[Fact] |
|
|
|
public void Supports_Null_Recycle_Key_When_Clearing_Items() |
|
|
|
{ |
|
|
|
using var app = App(); |
|
|
|
var (_, _, itemsControl) = CreateUnrootedTarget<NonRecyclingItemsControl>(); |
|
|
|
var root = CreateRoot(itemsControl); |
|
|
|
|
|
|
|
root.LayoutManager.ExecuteInitialLayoutPass(); |
|
|
|
|
|
|
|
var firstItem = itemsControl.ContainerFromIndex(0)!; |
|
|
|
itemsControl.ItemsSource = null; |
|
|
|
|
|
|
|
Layout(itemsControl); |
|
|
|
|
|
|
|
Assert.Null(firstItem.Parent); |
|
|
|
Assert.Null(firstItem.VisualParent); |
|
|
|
Assert.Empty(itemsControl.ItemsPanelRoot!.Children); |
|
|
|
} |
|
|
|
|
|
|
|
private static IReadOnlyList<int> GetRealizedIndexes(VirtualizingStackPanel target, ItemsControl itemsControl) |
|
|
|
{ |
|
|
|
return target.GetRealizedElements() |
|
|
|
@ -704,7 +742,7 @@ namespace Avalonia.Controls.UnitTests |
|
|
|
Optional<IDataTemplate?> itemTemplate = default, |
|
|
|
IEnumerable<Style>? styles = null) |
|
|
|
{ |
|
|
|
var (target, scroll, itemsControl) = CreateUnrootedTarget(items, itemTemplate); |
|
|
|
var (target, scroll, itemsControl) = CreateUnrootedTarget<ItemsControl>(items, itemTemplate); |
|
|
|
var root = CreateRoot(itemsControl, styles); |
|
|
|
|
|
|
|
root.LayoutManager.ExecuteInitialLayoutPass(); |
|
|
|
@ -712,9 +750,10 @@ namespace Avalonia.Controls.UnitTests |
|
|
|
return (target, scroll, itemsControl); |
|
|
|
} |
|
|
|
|
|
|
|
private static (VirtualizingStackPanel, ScrollViewer, ItemsControl) CreateUnrootedTarget( |
|
|
|
private static (VirtualizingStackPanel, ScrollViewer, T) CreateUnrootedTarget<T>( |
|
|
|
IEnumerable<object>? items = null, |
|
|
|
Optional<IDataTemplate?> itemTemplate = default) |
|
|
|
where T : ItemsControl, new() |
|
|
|
{ |
|
|
|
var target = new VirtualizingStackPanel(); |
|
|
|
|
|
|
|
@ -732,7 +771,7 @@ namespace Avalonia.Controls.UnitTests |
|
|
|
Template = ScrollViewerTemplate(), |
|
|
|
}; |
|
|
|
|
|
|
|
var itemsControl = new ItemsControl |
|
|
|
var itemsControl = new T |
|
|
|
{ |
|
|
|
ItemsSource = items, |
|
|
|
Template = new FuncControlTemplate<ItemsControl>((_, ns) => scroll.RegisterInNameScope(ns)), |
|
|
|
@ -806,5 +845,16 @@ namespace Avalonia.Controls.UnitTests |
|
|
|
|
|
|
|
public event NotifyCollectionChangedEventHandler? CollectionChanged; |
|
|
|
} |
|
|
|
|
|
|
|
private class NonRecyclingItemsControl : ItemsControl |
|
|
|
{ |
|
|
|
protected override Type StyleKeyOverride => typeof(ItemsControl); |
|
|
|
|
|
|
|
protected internal override bool NeedsContainerOverride(object? item, int index, out object? recycleKey) |
|
|
|
{ |
|
|
|
recycleKey = null; |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|