Browse Source

Fix TextBox in AdornerLayer causes collection modified exception in Arrange pass (#14714)

Bartosz Korczyński 1 year ago
parent
commit
65b1c4579e

+ 5 - 1
src/Avalonia.Controls/Primitives/VisualLayerManager.cs

@@ -160,8 +160,12 @@ namespace Avalonia.Controls.Primitives
         /// <inheritdoc />
         protected override Size ArrangeOverride(Size finalSize)
         {
-            foreach (var l in _layers)
+            for (var index = 0; index < _layers.Count; index++)
+            {
+                var l = _layers[index];
                 l.Arrange(new Rect(finalSize));
+            }
+
             return base.ArrangeOverride(finalSize);
         }
     }

+ 24 - 1
tests/Avalonia.Controls.UnitTests/TextBoxTests.cs

@@ -1406,7 +1406,7 @@ namespace Avalonia.Controls.UnitTests
         }
 
         [Fact]
-        public void TextBox_In_AdornerLayer_Will_Not_Cause_Collection_Modified_In_VisualLayerManager()
+        public void TextBox_In_AdornerLayer_Will_Not_Cause_Collection_Modified_In_VisualLayerManager_Measure()
         {
             using (UnitTestApplication.Start(Services))
             {
@@ -1428,6 +1428,29 @@ namespace Avalonia.Controls.UnitTests
             }
         }
 
+        [Fact]
+        public void TextBox_In_AdornerLayer_Will_Not_Cause_Collection_Modified_In_VisualLayerManager_Arrange()
+        {
+            using (UnitTestApplication.Start(Services))
+            {
+                var button = new Button();
+                var visualLayerManager = new VisualLayerManager() { Child = button };
+                var root = new TestRoot()
+                {
+                    Child = visualLayerManager
+                };
+                var adorner = new TextBox { Template = CreateTemplate(), Text = "a" };
+                var adornerLayer = AdornerLayer.GetAdornerLayer(button);
+
+                root.Measure(new Size(10, 10));
+
+                adornerLayer.Children.Add(adorner);
+                AdornerLayer.SetAdornedElement(adorner, button);
+
+                root.Arrange(new Rect(0, 0, 10, 10));
+            }
+        }
+
         [Theory]
         [InlineData("A\nBB\nCCC\nDDDD", 0, 0)]
         [InlineData("A\nBB\nCCC\nDDDD", 1, 2)]