Browse Source

Fix #5151 same as Microsoft

Mike Ward 5 years ago
parent
commit
eeb2745db5
1 changed files with 43 additions and 44 deletions
  1. 43 44
      src/Avalonia.Layout/ElementManager.cs

+ 43 - 44
src/Avalonia.Layout/ElementManager.cs

@@ -129,7 +129,7 @@ namespace Avalonia.Layout
         {
             for (int i = 0; i < count; i++)
             {
-                // Clear from the edges so that ItemsRepeater can optimize on maintaining 
+                // Clear from the edges so that ItemsRepeater can optimize on maintaining
                 // realized indices without walking through all the children every time.
                 int index = realizedIndex == 0 ? realizedIndex + i : (realizedIndex + count - 1) - i;
                 var elementRef = _realizedElements[index];
@@ -212,7 +212,7 @@ namespace Avalonia.Layout
         public ILayoutable GetRealizedElement(int dataIndex)
         {
             return IsVirtualizingContext ?
-                GetAt(GetRealizedRangeIndexFromDataIndex(dataIndex)) : 
+                GetAt(GetRealizedRangeIndexFromDataIndex(dataIndex)) :
                 _context.GetOrCreateElementAt(
                     dataIndex,
                     ElementRealizationOptions.ForceCreate | ElementRealizationOptions.SuppressAutoRecycle);
@@ -252,7 +252,6 @@ namespace Avalonia.Layout
                     (orientation == ScrollOrientation.Vertical ? ScrollOrientation.Horizontal : ScrollOrientation.Vertical) :
                     orientation;
 
-
                 var windowStart = effectiveOrientation == ScrollOrientation.Vertical ? window.Y : window.X;
                 var windowEnd = effectiveOrientation == ScrollOrientation.Vertical ? window.Y + window.Height : window.X + window.Width;
                 var firstElementStart = effectiveOrientation == ScrollOrientation.Vertical ? firstElementBounds.Y : firstElementBounds.X;
@@ -273,53 +272,53 @@ namespace Avalonia.Layout
                 switch (args.Action)
                 {
                     case NotifyCollectionChangedAction.Add:
-                    {
-                        OnItemsAdded(args.NewStartingIndex, args.NewItems.Count);
-                    }
-                    break;
+                        {
+                            OnItemsAdded(args.NewStartingIndex, args.NewItems.Count);
+                        }
+                        break;
 
                     case NotifyCollectionChangedAction.Replace:
-                    {
-                        int oldSize = args.OldItems.Count;
-                        int newSize = args.NewItems.Count;
-                        int oldStartIndex = args.OldStartingIndex;
-                        int newStartIndex = args.NewStartingIndex;
-
-                        if (oldSize == newSize &&
-                            oldStartIndex == newStartIndex &&
-                            IsDataIndexRealized(oldStartIndex) &&
-                            IsDataIndexRealized(oldStartIndex + oldSize -1))
                         {
-                            // Straight up replace of n items within the realization window.
-                            // Removing and adding might causes us to lose the anchor causing us
-                            // to throw away all containers and start from scratch.
-                            // Instead, we can just clear those items and set the element to
-                            // null (sentinel) and let the next measure get new containers for them.
-                            var startRealizedIndex = GetRealizedRangeIndexFromDataIndex(oldStartIndex);
-                            for (int realizedIndex = startRealizedIndex; realizedIndex < startRealizedIndex + oldSize; realizedIndex++)
+                            int oldSize = args.OldItems.Count;
+                            int newSize = args.NewItems.Count;
+                            int oldStartIndex = args.OldStartingIndex;
+                            int newStartIndex = args.NewStartingIndex;
+
+                            if (oldSize == newSize &&
+                                oldStartIndex == newStartIndex &&
+                                IsDataIndexRealized(oldStartIndex) &&
+                                IsDataIndexRealized(oldStartIndex + oldSize - 1))
                             {
-                                var elementRef = _realizedElements[realizedIndex];
-
-                                if (elementRef != null)
+                                // Straight up replace of n items within the realization window.
+                                // Removing and adding might causes us to lose the anchor causing us
+                                // to throw away all containers and start from scratch.
+                                // Instead, we can just clear those items and set the element to
+                                // null (sentinel) and let the next measure get new containers for them.
+                                var startRealizedIndex = GetRealizedRangeIndexFromDataIndex(oldStartIndex);
+                                for (int realizedIndex = startRealizedIndex; realizedIndex < startRealizedIndex + oldSize; realizedIndex++)
                                 {
-                                    _context.RecycleElement(elementRef);
-                                    _realizedElements[realizedIndex] = null;
+                                    var elementRef = _realizedElements[realizedIndex];
+
+                                    if (elementRef != null)
+                                    {
+                                        _context.RecycleElement(elementRef);
+                                        _realizedElements[realizedIndex] = null;
+                                    }
                                 }
                             }
+                            else
+                            {
+                                OnItemsRemoved(oldStartIndex, oldSize);
+                                OnItemsAdded(newStartIndex, newSize);
+                            }
                         }
-                        else
-                        {
-                            OnItemsRemoved(oldStartIndex, oldSize);
-                            OnItemsAdded(newStartIndex, newSize);
-                        }
-                    }
-                    break;
+                        break;
 
                     case NotifyCollectionChangedAction.Remove:
-                    {
-                        OnItemsRemoved(args.OldStartingIndex, args.OldItems.Count);
-                    }
-                    break;
+                        {
+                            OnItemsRemoved(args.OldStartingIndex, args.OldItems.Count);
+                        }
+                        break;
 
                     case NotifyCollectionChangedAction.Reset:
                         ClearRealizedRange();
@@ -376,7 +375,7 @@ namespace Avalonia.Layout
             int backCutoffIndex = realizedRangeSize;
 
             for (int i = 0;
-                i<realizedRangeSize &&
+                i < realizedRangeSize &&
                 !Intersects(window, _realizedElementLayoutBounds[i], orientation);
                 ++i)
             {
@@ -391,7 +390,7 @@ namespace Avalonia.Layout
                 --backCutoffIndex;
             }
 
-            if (backCutoffIndex<realizedRangeSize - 1)
+            if (backCutoffIndex < realizedRangeSize - 1)
             {
                 ClearRealizedRange(backCutoffIndex + 1, realizedRangeSize - backCutoffIndex - 1);
             }
@@ -419,14 +418,14 @@ namespace Avalonia.Layout
             // to insert items.
             int lastRealizedDataIndex = _firstRealizedDataIndex + GetRealizedElementCount() - 1;
             int newStartingIndex = index;
-            if (newStartingIndex > _firstRealizedDataIndex &&
+            if (newStartingIndex >= _firstRealizedDataIndex &&
                 newStartingIndex <= lastRealizedDataIndex)
             {
                 // Inserted within the realized range
                 int insertRangeStartIndex = newStartingIndex - _firstRealizedDataIndex;
                 for (int i = 0; i < count; i++)
                 {
-                    // Insert null (sentinel) here instead of an element, that way we dont 
+                    // Insert null (sentinel) here instead of an element, that way we dont
                     // end up creating a lot of elements only to be thrown out in the next layout.
                     int insertRangeIndex = insertRangeStartIndex + i;
                     int dataIndex = newStartingIndex + i;