|
|
@@ -47,7 +47,7 @@ namespace Avalonia.Controls.Presenters
|
|
|
|
|
|
if (delta != 0)
|
|
|
{
|
|
|
- RecycleContainers(delta);
|
|
|
+ RecycleMoveContainers(delta);
|
|
|
FirstIndex += delta;
|
|
|
NextIndex += delta;
|
|
|
}
|
|
|
@@ -56,7 +56,7 @@ namespace Avalonia.Controls.Presenters
|
|
|
{
|
|
|
// We're moving to a partially obscured item at the end of the list.
|
|
|
var firstIndex = ItemCount - panel.Children.Count;
|
|
|
- RecycleContainers(firstIndex - FirstIndex);
|
|
|
+ RecycleMoveContainers(firstIndex - FirstIndex);
|
|
|
NextIndex = ItemCount;
|
|
|
FirstIndex = NextIndex - panel.Children.Count;
|
|
|
panel.PixelOffset = VirtualizingPanel.PixelOverflow;
|
|
|
@@ -85,14 +85,26 @@ namespace Avalonia.Controls.Presenters
|
|
|
{
|
|
|
base.ItemsChanged(items, e);
|
|
|
|
|
|
- if (e.Action == NotifyCollectionChangedAction.Reset)
|
|
|
+ switch (e.Action)
|
|
|
{
|
|
|
- // We could recycle items here if this proves to be inefficient, but
|
|
|
- // Reset indicates a large change and should (?) be quite rare.
|
|
|
- VirtualizingPanel.Children.Clear();
|
|
|
- Owner.ItemContainerGenerator.Clear();
|
|
|
- FirstIndex = NextIndex = 0;
|
|
|
- CreateRemoveContainers();
|
|
|
+ case NotifyCollectionChangedAction.Add:
|
|
|
+ if (e.NewStartingIndex >= FirstIndex &&
|
|
|
+ e.NewStartingIndex + e.NewItems.Count < NextIndex)
|
|
|
+ {
|
|
|
+ CreateRemoveContainers();
|
|
|
+ RecycleContainers();
|
|
|
+ }
|
|
|
+
|
|
|
+ break;
|
|
|
+
|
|
|
+ case NotifyCollectionChangedAction.Reset:
|
|
|
+ // We could recycle items here if this proves to be inefficient, but
|
|
|
+ // Reset indicates a large change and should (?) be quite rare.
|
|
|
+ VirtualizingPanel.Children.Clear();
|
|
|
+ Owner.ItemContainerGenerator.Clear();
|
|
|
+ FirstIndex = NextIndex = 0;
|
|
|
+ CreateRemoveContainers();
|
|
|
+ break;
|
|
|
}
|
|
|
|
|
|
((ILogicalScrollable)Owner).InvalidateScroll();
|
|
|
@@ -161,7 +173,31 @@ namespace Avalonia.Controls.Presenters
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- private void RecycleContainers(int delta)
|
|
|
+ private void RecycleContainers()
|
|
|
+ {
|
|
|
+ var panel = VirtualizingPanel;
|
|
|
+ var generator = Owner.ItemContainerGenerator;
|
|
|
+ var selector = Owner.MemberSelector;
|
|
|
+ var containers = generator.Containers.ToList();
|
|
|
+ var itemIndex = FirstIndex;
|
|
|
+
|
|
|
+ foreach (var container in containers)
|
|
|
+ {
|
|
|
+ var item = Items.ElementAt(itemIndex);
|
|
|
+
|
|
|
+ if (!object.Equals(container.Item, item))
|
|
|
+ {
|
|
|
+ if (!generator.TryRecycle(itemIndex, itemIndex, item, selector))
|
|
|
+ {
|
|
|
+ throw new NotImplementedException();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ ++itemIndex;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void RecycleMoveContainers(int delta)
|
|
|
{
|
|
|
var panel = VirtualizingPanel;
|
|
|
var generator = Owner.ItemContainerGenerator;
|