diff --git a/src/Avalonia.Controls/Presenters/ScrollContentPresenter.cs b/src/Avalonia.Controls/Presenters/ScrollContentPresenter.cs index 5e20e8d3c9..25fe728d49 100644 --- a/src/Avalonia.Controls/Presenters/ScrollContentPresenter.cs +++ b/src/Avalonia.Controls/Presenters/ScrollContentPresenter.cs @@ -59,6 +59,7 @@ namespace Avalonia.Controls.Presenters static ScrollContentPresenter() { ClipToBoundsProperty.OverrideDefaultValue(typeof(ScrollContentPresenter), true); + ChildProperty.Changed.AddClassHandler(x => x.ChildChanged); AffectsArrange(OffsetProperty); } @@ -258,6 +259,16 @@ namespace Avalonia.Controls.Presenters e.Handled = BringDescendentIntoView(e.TargetObject, e.TargetRect); } + private void ChildChanged(AvaloniaPropertyChangedEventArgs e) + { + UpdateScrollableSubscription((IControl)e.NewValue); + + if (e.OldValue != null) + { + Offset = default(Vector); + } + } + private void UpdateScrollableSubscription(IControl child) { var scrollable = child as ILogicalScrollable; @@ -286,12 +297,7 @@ namespace Avalonia.Controls.Presenters if (logicalScroll != scrollable.IsLogicalScrollEnabled) { UpdateScrollableSubscription(Child); - - if (!scrollable.IsLogicalScrollEnabled) - { - Offset = default(Vector); - } - + Offset = default(Vector); InvalidateMeasure(); } diff --git a/tests/Avalonia.Controls.UnitTests/Avalonia.Controls.UnitTests.csproj b/tests/Avalonia.Controls.UnitTests/Avalonia.Controls.UnitTests.csproj index d3a48c02b0..3732f13769 100644 --- a/tests/Avalonia.Controls.UnitTests/Avalonia.Controls.UnitTests.csproj +++ b/tests/Avalonia.Controls.UnitTests/Avalonia.Controls.UnitTests.csproj @@ -109,7 +109,7 @@ - + diff --git a/tests/Avalonia.Controls.UnitTests/Presenters/ScrollContentPresenterTests_ILogicalScrollable.cs b/tests/Avalonia.Controls.UnitTests/Presenters/ScrollContentPresenterTests_ILogicalScrollable.cs index 8f3bee3bb9..5a7e5f9f8b 100644 --- a/tests/Avalonia.Controls.UnitTests/Presenters/ScrollContentPresenterTests_ILogicalScrollable.cs +++ b/tests/Avalonia.Controls.UnitTests/Presenters/ScrollContentPresenterTests_ILogicalScrollable.cs @@ -236,6 +236,56 @@ namespace Avalonia.Controls.UnitTests Assert.Equal(new Rect(0, 0, 100, 100), scrollable.Bounds); } + [Fact] + public void Changing_Content_Should_Update_State() + { + var logicalScrollable = new TestScrollable + { + Extent = new Size(100, 100), + Offset = new Vector(50, 50), + Viewport = new Size(25, 25), + }; + + var nonLogicalScrollable = new TestScrollable + { + IsLogicalScrollEnabled = false, + }; + + var target = new ScrollContentPresenter + { + Content = logicalScrollable, + }; + + target.UpdateChild(); + target.Measure(new Size(100, 100)); + target.Arrange(new Rect(0, 0, 100, 100)); + + Assert.Equal(logicalScrollable.Extent, target.Extent); + Assert.Equal(logicalScrollable.Offset, target.Offset); + Assert.Equal(logicalScrollable.Viewport, target.Viewport); + Assert.Equal(new Rect(0, 0, 100, 100), logicalScrollable.Bounds); + + target.Content = nonLogicalScrollable; + target.UpdateChild(); + target.Measure(new Size(100, 100)); + target.Arrange(new Rect(0, 0, 100, 100)); + + Assert.Equal(new Size(150, 150), target.Extent); + Assert.Equal(new Vector(0, 0), target.Offset); + Assert.Equal(new Size(100, 100), target.Viewport); + Assert.Equal(new Rect(0, 0, 150, 150), nonLogicalScrollable.Bounds); + + target.Content = logicalScrollable; + target.UpdateChild(); + target.Measure(new Size(100, 100)); + target.Arrange(new Rect(0, 0, 100, 100)); + + Assert.Equal(logicalScrollable.Extent, target.Extent); + Assert.Equal(logicalScrollable.Offset, target.Offset); + Assert.Equal(logicalScrollable.Viewport, target.Viewport); + Assert.Equal(new Rect(0, 0, 100, 100), logicalScrollable.Bounds); + } + private class TestScrollable : Control, ILogicalScrollable { private Size _extent;