diff --git a/src/Avalonia.Controls/VirtualizingCarouselPanel.cs b/src/Avalonia.Controls/VirtualizingCarouselPanel.cs index 958c19826d..d10ae124c1 100644 --- a/src/Avalonia.Controls/VirtualizingCarouselPanel.cs +++ b/src/Avalonia.Controls/VirtualizingCarouselPanel.cs @@ -158,7 +158,15 @@ namespace Avalonia.Controls GetTransition() is { } transition) { _transition = new CancellationTokenSource(); - transition.Start(_transitionFrom, to, _realizedIndex > _transitionFromIndex, _transition.Token) + + var forward = (_realizedIndex > _transitionFromIndex); + if (Items.Count > 2) + { + forward = forward || (_transitionFromIndex == Items.Count - 1 && _realizedIndex == 0); + forward = forward && !(_transitionFromIndex == 0 && _realizedIndex == Items.Count - 1); + } + + transition.Start(_transitionFrom, to, forward, _transition.Token) .ContinueWith(TransitionFinished, TaskScheduler.FromCurrentSynchronizationContext()); } diff --git a/tests/Avalonia.Controls.UnitTests/VirtualizingCarouselPanelTests.cs b/tests/Avalonia.Controls.UnitTests/VirtualizingCarouselPanelTests.cs index 5e276b5911..4f3b2f588f 100644 --- a/tests/Avalonia.Controls.UnitTests/VirtualizingCarouselPanelTests.cs +++ b/tests/Avalonia.Controls.UnitTests/VirtualizingCarouselPanelTests.cs @@ -147,6 +147,55 @@ namespace Avalonia.Controls.UnitTests Times.Once); } + [Fact] + public void Changing_SelectedIndex_transitions_forward_cycle() + { + using var app = Start(); + var items = new Control[] { new Button(), new Canvas(), new Label() }; + var transition = new Mock(); + var (target, carousel) = CreateTarget(items, transition.Object); + var cycleindexes = new[] { 1, 2, 0}; + + for (int cycleIndex = 0; cycleIndex < cycleindexes.Length; cycleIndex++) + { + carousel.SelectedIndex = cycleindexes[cycleIndex]; + Layout(target); + + var index = cycleIndex; + transition.Verify(x => x.Start( + index > 0 ? items[cycleindexes[index - 1]] : items[0], + items[cycleindexes[index]], + true, + It.IsAny()), + Times.Once); + } + } + + [Fact] + public void Changing_SelectedIndex_transitions_backward_cycle() + { + using var app = Start(); + var items = new Control[] { new Button(), new Canvas(), new Label() }; + var transition = new Mock(); + var (target, carousel) = CreateTarget(items, transition.Object); + + var cycleindexes = new[] { 2, 1, 0}; + + for (int cycleIndex = 0; cycleIndex < cycleindexes.Length; cycleIndex++) + { + carousel.SelectedIndex = cycleindexes[cycleIndex]; + Layout(target); + + var index = cycleIndex; + transition.Verify(x => x.Start( + index > 0 ? items[cycleindexes[index - 1]] : items[0], + items[cycleindexes[index]], + false, + It.IsAny()), + Times.Once); + } + } + [Fact] public void TransitionFrom_Control_Is_Recycled_When_Transition_Completes() {