Browse Source

Added failing test for #11161.

Steven Kirk 2 years ago
parent
commit
c4a5567090

+ 33 - 0
tests/Avalonia.Base.UnitTests/Layout/LayoutManagerTests.cs

@@ -514,5 +514,38 @@ namespace Avalonia.Base.UnitTests.Layout
             Assert.True(parent.IsMeasureValid);
             Assert.True(parent.IsArrangeValid);
         }
+
+        [Fact]
+        public void Grandparent_Can_Invalidate_Root_Measure_During_Arrange()
+        {
+            // Issue #11161.
+            var child = new LayoutTestControl();
+            var parent = new LayoutTestControl { Child = child };
+            var grandparent = new LayoutTestControl { Child = parent };
+            var root = new LayoutTestRoot { Child = grandparent };
+
+            root.LayoutManager.ExecuteInitialLayoutPass();
+
+            grandparent.DoArrangeOverride = (_, s) =>
+            {
+                root.InvalidateMeasure();
+                return s;
+            };
+            grandparent.CallBaseArrange = true;
+
+            child.InvalidateMeasure();
+            grandparent.InvalidateMeasure();
+
+            root.LayoutManager.ExecuteLayoutPass();
+
+            Assert.True(child.IsMeasureValid);
+            Assert.True(child.IsArrangeValid);
+            Assert.True(parent.IsMeasureValid);
+            Assert.True(parent.IsArrangeValid);
+            Assert.True(grandparent.IsMeasureValid);
+            Assert.True(grandparent.IsArrangeValid);
+            Assert.True(root.IsMeasureValid);
+            Assert.True(root.IsArrangeValid);
+        }
     }
 }

+ 26 - 6
tests/Avalonia.Base.UnitTests/Layout/LayoutTestControl.cs

@@ -10,21 +10,41 @@ namespace Avalonia.Base.UnitTests.Layout
         public bool Arranged { get; set; }
         public Func<Layoutable, Size, Size> DoMeasureOverride { get; set; }
         public Func<Layoutable, Size, Size> DoArrangeOverride { get; set; }
+        public bool CallBaseMeasure { get; set; }
+        public bool CallBaseArrange { get; set; }
 
         protected override Size MeasureOverride(Size availableSize)
         {
             Measured = true;
-            return DoMeasureOverride != null ?
-                DoMeasureOverride(this, availableSize) :
-                base.MeasureOverride(availableSize);
+
+            if (DoMeasureOverride is not null)
+            {
+                var overrideResult = DoMeasureOverride(this, availableSize);
+                return CallBaseMeasure ?
+                    base.MeasureOverride(overrideResult) :
+                    overrideResult;
+            }
+            else
+            {
+                return base.MeasureOverride(availableSize);
+            }
         }
 
         protected override Size ArrangeOverride(Size finalSize)
         {
             Arranged = true;
-            return DoArrangeOverride != null ?
-                DoArrangeOverride(this, finalSize) :
-                base.ArrangeOverride(finalSize);
+
+            if (DoArrangeOverride is not null)
+            {
+                var overrideResult = DoArrangeOverride(this, finalSize);
+                return CallBaseArrange ?
+                    base.ArrangeOverride(overrideResult) :
+                    overrideResult;
+            }
+            else
+            {
+                return base.ArrangeOverride(finalSize);
+            }
         }
     }
 }