Browse Source

Merge pull request #8122 from AvaloniaUI/fixes/viewbox-logical-parent

Don't expose Viewbox container as logical child.
pull/8152/head
Steven Kirk 4 years ago
committed by GitHub
parent
commit
0a56ae8fd5
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 50
      src/Avalonia.Controls/Viewbox.cs
  2. 20
      tests/Avalonia.Controls.UnitTests/ViewboxTests.cs

50
src/Avalonia.Controls/Viewbox.cs

@ -8,7 +8,7 @@ namespace Avalonia.Controls
/// </summary> /// </summary>
public class Viewbox : Control public class Viewbox : Control
{ {
private Decorator _containerVisual; private ViewboxContainer _containerVisual;
/// <summary> /// <summary>
/// Defines the <see cref="Stretch"/> property. /// Defines the <see cref="Stretch"/> property.
@ -37,9 +37,10 @@ namespace Avalonia.Controls
public Viewbox() public Viewbox()
{ {
_containerVisual = new Decorator(); // The Child control is hosted inside a ViewboxContainer control so that the transform
// can be applied independently of the Viewbox and Child transforms.
_containerVisual = new ViewboxContainer();
_containerVisual.RenderTransformOrigin = RelativePoint.TopLeft; _containerVisual.RenderTransformOrigin = RelativePoint.TopLeft;
LogicalChildren.Add(_containerVisual);
VisualChildren.Add(_containerVisual); VisualChildren.Add(_containerVisual);
} }
@ -88,7 +89,22 @@ namespace Avalonia.Controls
if (change.Property == ChildProperty) if (change.Property == ChildProperty)
{ {
_containerVisual.Child = change.GetNewValue<IControl>(); var (oldChild, newChild) = change.GetOldAndNewValue<IControl>();
if (oldChild is not null)
{
((ISetLogicalParent)oldChild).SetParent(null);
LogicalChildren.Remove(oldChild);
}
_containerVisual.Child = newChild;
if (newChild is not null)
{
((ISetLogicalParent)newChild).SetParent(this);
LogicalChildren.Add(newChild);
}
InvalidateMeasure(); InvalidateMeasure();
} }
} }
@ -129,5 +145,31 @@ namespace Avalonia.Controls
return finalSize; return finalSize;
} }
/// <summary>
/// A simple container control which hosts its child as a visual but not logical child.
/// </summary>
private class ViewboxContainer : Control
{
private IControl? _child;
public IControl? Child
{
get => _child;
set
{
if (_child != value)
{
if (_child is not null)
VisualChildren.Remove(_child);
_child = value;
if (_child is not null)
VisualChildren.Add(_child);
}
}
}
}
} }
} }

20
tests/Avalonia.Controls.UnitTests/ViewboxTests.cs

@ -1,4 +1,5 @@
using Avalonia.Controls.Shapes; using Avalonia.Controls.Shapes;
using Avalonia.LogicalTree;
using Avalonia.Media; using Avalonia.Media;
using Avalonia.UnitTests; using Avalonia.UnitTests;
using Xunit; using Xunit;
@ -170,5 +171,24 @@ namespace Avalonia.Controls.UnitTests
Assert.Equal(expectedScale, scaleTransform.ScaleX); Assert.Equal(expectedScale, scaleTransform.ScaleX);
Assert.Equal(expectedScale, scaleTransform.ScaleY); Assert.Equal(expectedScale, scaleTransform.ScaleY);
} }
[Fact]
public void Child_Should_Be_Logical_Child_Of_Viewbox()
{
var target = new Viewbox();
Assert.Empty(target.GetLogicalChildren());
var child = new Canvas();
target.Child = child;
Assert.Single(target.GetLogicalChildren(), child);
Assert.Same(child.GetLogicalParent(), target);
target.Child = null;
Assert.Empty(target.GetLogicalChildren());
Assert.Null(child.GetLogicalParent());
}
} }
} }

Loading…
Cancel
Save