Browse Source

Merge pull request #7555 from AvaloniaUI/fixes/7552-visibility-layout-invalidation

Fix visibility layout invalidation
pull/8163/head
Max Katz 4 years ago
committed by GitHub
parent
commit
dbba7fe309
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 20
      src/Avalonia.Base/Layout/Layoutable.cs
  2. 97
      tests/Avalonia.Base.UnitTests/Layout/LayoutableTests.cs

20
src/Avalonia.Base/Layout/Layoutable.cs

@ -141,7 +141,6 @@ namespace Avalonia.Layout
static Layoutable()
{
AffectsMeasure<Layoutable>(
IsVisibleProperty,
WidthProperty,
HeightProperty,
MinWidthProperty,
@ -791,6 +790,25 @@ namespace Avalonia.Layout
{
}
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
{
base.OnPropertyChanged(change);
if (change.Property == IsVisibleProperty)
{
DesiredSize = default;
// All changes to visibility cause the parent element to be notified.
this.GetVisualParent<ILayoutable>()?.ChildDesiredSizeChanged(this);
// We only invalidate outselves when visibility is changed to true.
if (change.GetNewValue<bool>())
{
InvalidateMeasure();
}
}
}
/// <inheritdoc/>
protected sealed override void OnVisualParentChanged(IVisual? oldParent, IVisual? newParent)
{

97
tests/Avalonia.Base.UnitTests/Layout/LayoutableTests.cs

@ -321,6 +321,103 @@ namespace Avalonia.Base.UnitTests.Layout
Times.Once);
}
[Fact]
public void Making_Control_Invisible_Should_Invalidate_Parent_Measure()
{
Border child;
var target = new StackPanel
{
Children =
{
(child = new Border
{
Width = 100,
}),
}
};
target.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
target.Arrange(new Rect(target.DesiredSize));
Assert.True(target.IsMeasureValid);
Assert.True(target.IsArrangeValid);
Assert.True(child.IsMeasureValid);
Assert.True(child.IsArrangeValid);
child.IsVisible = false;
Assert.False(target.IsMeasureValid);
Assert.False(target.IsArrangeValid);
Assert.True(child.IsMeasureValid);
Assert.True(child.IsArrangeValid);
}
[Fact]
public void Making_Control_Visible_Should_Invalidate_Own_And_Parent_Measure()
{
Border child;
var target = new StackPanel
{
Children =
{
(child = new Border
{
Width = 100,
IsVisible = false,
}),
}
};
target.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
target.Arrange(new Rect(target.DesiredSize));
Assert.True(target.IsMeasureValid);
Assert.True(target.IsArrangeValid);
Assert.True(child.IsMeasureValid);
Assert.False(child.IsArrangeValid);
child.IsVisible = true;
Assert.False(target.IsMeasureValid);
Assert.False(target.IsArrangeValid);
Assert.False(child.IsMeasureValid);
Assert.False(child.IsArrangeValid);
}
[Fact]
public void Measuring_Invisible_Control_Should_Not_Invalidate_Parent_Measure()
{
Border child;
var target = new StackPanel
{
Children =
{
(child = new Border
{
Width = 100,
}),
}
};
target.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
target.Arrange(new Rect(target.DesiredSize));
Assert.True(target.IsMeasureValid);
Assert.True(target.IsArrangeValid);
Assert.Equal(new Size(100, 0), child.DesiredSize);
child.IsVisible = false;
Assert.Equal(default, child.DesiredSize);
target.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
target.Arrange(new Rect(target.DesiredSize));
child.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
Assert.True(target.IsMeasureValid);
Assert.True(target.IsArrangeValid);
Assert.Equal(default, child.DesiredSize);
}
private class TestLayoutable : Layoutable
{
public Size ArrangeSize { get; private set; }

Loading…
Cancel
Save