Browse Source

Merge pull request #11175 from AvaloniaUI/fixes/11161-layout-invalidation

Fix another layout invalidation problem.
pull/11158/head
Max Katz 3 years ago
committed by GitHub
parent
commit
f456ea21c5
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 8
      src/Avalonia.Base/Layout/LayoutManager.cs
  2. 33
      tests/Avalonia.Base.UnitTests/Layout/LayoutManagerTests.cs
  3. 32
      tests/Avalonia.Base.UnitTests/Layout/LayoutTestControl.cs

8
src/Avalonia.Base/Layout/LayoutManager.cs

@ -249,10 +249,12 @@ namespace Avalonia.Layout
{
var control = _toMeasure.Dequeue();
if (!control.IsMeasureValid && control.IsAttachedToVisualTree)
if (!control.IsMeasureValid)
{
Measure(control);
}
_toArrange.Enqueue(control);
}
}
@ -262,7 +264,7 @@ namespace Avalonia.Layout
{
var control = _toArrange.Dequeue();
if (!control.IsArrangeValid && control.IsAttachedToVisualTree)
if (!control.IsArrangeValid)
{
Arrange(control);
}
@ -297,8 +299,6 @@ namespace Avalonia.Layout
{
control.Measure(control.PreviousMeasure.Value);
}
_toArrange.Enqueue(control);
}
return true;

33
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);
}
}
}

32
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);
}
}
}
}

Loading…
Cancel
Save