Browse Source

Invalidate measure when control removed

When a control's parent changes, invalidate its measure and the measure
of all descendents.
Steven Kirk 9 years ago
parent
commit
c554467d13

+ 11 - 0
src/Avalonia.Layout/Layoutable.cs

@@ -603,6 +603,17 @@ namespace Avalonia.Layout
             return finalSize;
         }
 
+        /// <inheritdoc/>
+        protected override sealed void OnVisualParentChanged(IVisual oldParent, IVisual newParent)
+        {
+            foreach (ILayoutable i in this.GetSelfAndVisualDescendents())
+            {
+                i.InvalidateMeasure();
+            }
+
+            base.OnVisualParentChanged(oldParent, newParent);
+        }
+
         /// <summary>
         /// Calls <see cref="InvalidateMeasure"/> on the control on which a property changed.
         /// </summary>

+ 11 - 1
src/Avalonia.SceneGraph/Visual.cs

@@ -384,6 +384,16 @@ namespace Avalonia
             DetachedFromVisualTree?.Invoke(this, e);
         }
 
+        /// <summary>
+        /// Called when the control's visual parent changes.
+        /// </summary>
+        /// <param name="oldParent">The old visual parent.</param>
+        /// <param name="newParent">The new visual parent.</param>
+        protected virtual void OnVisualParentChanged(IVisual oldParent, IVisual newParent)
+        {
+            RaisePropertyChanged(VisualParentProperty, oldParent, newParent, BindingPriority.LocalValue);
+        }
+
         /// <summary>
         /// Called when a property changes that should invalidate the visual.
         /// </summary>
@@ -499,7 +509,7 @@ namespace Avalonia
                 OnAttachedToVisualTreeCore(e);
             }
 
-            RaisePropertyChanged(VisualParentProperty, old, value, BindingPriority.LocalValue);
+            OnVisualParentChanged(old, value);
         }
 
         /// <summary>

+ 17 - 0
tests/Avalonia.Layout.UnitTests/MeasureTests.cs

@@ -44,6 +44,23 @@ namespace Avalonia.Layout.UnitTests
             Assert.Equal(new Size(0, 0), panel.DesiredSize);
         }
 
+        [Fact]
+        public void Removing_From_Parent_Should_Invalidate_Measure_Of_Control_And_Descendents()
+        {
+            var panel = new StackPanel();
+            var child2 = new Border();
+            var child1 = new Border { Child = child2 };
+            panel.Children.Add(child1);
+
+            panel.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
+            Assert.True(child1.IsMeasureValid);
+            Assert.True(child2.IsMeasureValid);
+
+            panel.Children.Remove(child1);
+            Assert.False(child1.IsMeasureValid);
+            Assert.False(child2.IsMeasureValid);
+        }
+
         [Fact]
         public void Negative_Margin_Larger_Than_Constraint_Should_Request_Width_0()
         {