diff --git a/src/Avalonia.Controls/Presenters/ScrollContentPresenter.cs b/src/Avalonia.Controls/Presenters/ScrollContentPresenter.cs index 04f6b1d8a1..aa62eaaf06 100644 --- a/src/Avalonia.Controls/Presenters/ScrollContentPresenter.cs +++ b/src/Avalonia.Controls/Presenters/ScrollContentPresenter.cs @@ -285,8 +285,12 @@ namespace Avalonia.Controls.Presenters return false; } + var oldOffset = Offset; SetCurrentValue(OffsetProperty, offset); - return true; + + // It's possible that the Offset coercion has changed the offset back to its previous value, + // this is common for floating point rounding errors. + return !Offset.NearlyEquals(oldOffset); } protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e) diff --git a/tests/Avalonia.Controls.UnitTests/Presenters/ScrollContentPresenterTests.cs b/tests/Avalonia.Controls.UnitTests/Presenters/ScrollContentPresenterTests.cs index 274bee1528..e70ab52043 100644 --- a/tests/Avalonia.Controls.UnitTests/Presenters/ScrollContentPresenterTests.cs +++ b/tests/Avalonia.Controls.UnitTests/Presenters/ScrollContentPresenterTests.cs @@ -439,6 +439,56 @@ namespace Avalonia.Controls.UnitTests.Presenters Assert.Equal(new Vector(0, 0), innerPresenter.Offset); } + [Fact] + public void Nested_Presenters_Should_Scroll_Outer_When_Viewports_Are_Close() + { + ScrollContentPresenter innerPresenter; + Border border; + + var outerPresenter = new ScrollContentPresenter + { + CanHorizontallyScroll = true, + CanVerticallyScroll = true, + Width = 100, + Height = 170.0568181818182, + UseLayoutRounding = false, + Content = innerPresenter = new ScrollContentPresenter + { + CanHorizontallyScroll = true, + CanVerticallyScroll = true, + Width = 100, + Height = 493.2613636363636, + UseLayoutRounding = false, + Content = new StackPanel + { + Children = + { + new Border + { + Height = 455.31818181818187, + UseLayoutRounding = false + }, + (border = new Border { + Width = 100, + Height = 37.94318181818182, + UseLayoutRounding = false + }) + } + } + } + }; + + innerPresenter.UpdateChild(); + outerPresenter.UpdateChild(); + outerPresenter.Measure(new Size(100, 170.0568181818182)); + outerPresenter.Arrange(new Rect(0, 0, 100, 170.0568181818182)); + + border.BringIntoView(); + + Assert.Equal(new Vector(0, 323.20454545454544), outerPresenter.Offset); + Assert.Equal(new Vector(0, 0), innerPresenter.Offset); + } + private class TestControl : Control { public Size AvailableSize { get; private set; }