Browse Source

Attach to panel before preparing container.

Steven Kirk 3 years ago
parent
commit
2c4572a98e

+ 9 - 0
src/Avalonia.Controls/ItemsControl.cs

@@ -16,6 +16,7 @@ using Avalonia.Input;
 using Avalonia.LogicalTree;
 using Avalonia.Metadata;
 using Avalonia.Styling;
+using Avalonia.VisualTree;
 
 namespace Avalonia.Controls
 {
@@ -479,6 +480,14 @@ namespace Avalonia.Controls
 
         internal void PrepareItemContainer(Control container, object? item, int index)
         {
+            // Putting this precondition in place in case we want to raise an event when a
+            // container is realized. If we want to do that, then the event subscriber will expect
+            // the container to be attached to the tree. Not using IsAttachedToVisualTree here
+            // because a bunch of tests don't have a rooted visual tree.
+            if (container.GetVisualParent() is null)
+                throw new InvalidOperationException(
+                    "Container must be attached to parent before PrepareItemContainer is called.");
+
             var itemContainerTheme = ItemContainerTheme;
 
             if (itemContainerTheme is not null && 

+ 7 - 6
src/Avalonia.Controls/Presenters/PanelContainerGenerator.cs

@@ -70,10 +70,7 @@ namespace Avalonia.Controls.Presenters
             {
                 var i = index;
                 foreach (var item in items)
-                {
-                    children.Insert(i, CreateContainer(itemsControl, item, i));
-                    ++i;
-                }
+                    InsertContainer(itemsControl, children, item, i++);
 
                 var childCount = children.Count;
                 var delta = i - index;
@@ -124,7 +121,11 @@ namespace Avalonia.Controls.Presenters
             }
         }
 
-        private static Control CreateContainer(ItemsControl itemsControl, object? item, int index)
+        private static void InsertContainer(
+            ItemsControl itemsControl,
+            Controls children,
+            object? item, 
+            int index)
         {
             var generator = itemsControl.ItemContainerGenerator;
             Control container;
@@ -140,8 +141,8 @@ namespace Avalonia.Controls.Presenters
             }
 
             itemsControl.AddLogicalChild(container);
+            children.Insert(index, container);
             generator.PrepareItemContainer(container, item, index);
-            return container;
         }
 
         private void ClearItemsControlLogicalChildren()

+ 1 - 1
src/Avalonia.Controls/VirtualizingStackPanel.cs

@@ -458,9 +458,9 @@ namespace Avalonia.Controls
                 }
                 else if (generator.IsItemItsOwnContainer(controlItem))
                 {
+                    AddInternalChild(controlItem);
                     generator.PrepareItemContainer(controlItem, item, index);
                     controlItem.SetValue(ItemIsOwnContainerProperty, true);
-                    AddInternalChild(controlItem);
                     return controlItem;
                 }
             }