diff --git a/src/Avalonia.Controls/Presenters/CarouselPresenter.cs b/src/Avalonia.Controls/Presenters/CarouselPresenter.cs
index c6ef5a14e9..144174e371 100644
--- a/src/Avalonia.Controls/Presenters/CarouselPresenter.cs
+++ b/src/Avalonia.Controls/Presenters/CarouselPresenter.cs
@@ -106,7 +106,6 @@ namespace Avalonia.Controls.Presenters
///
protected override void ItemsChanged(NotifyCollectionChangedEventArgs e)
{
- // TODO: Handle items changing.
switch (e.Action)
{
case NotifyCollectionChangedAction.Remove:
@@ -115,9 +114,21 @@ namespace Avalonia.Controls.Presenters
var generator = ItemContainerGenerator;
var containers = generator.RemoveRange(e.OldStartingIndex, e.OldItems.Count);
Panel.Children.RemoveAll(containers.Select(x => x.ContainerControl));
+
+ MoveToPage(-1, SelectedIndex);
}
break;
+ case NotifyCollectionChangedAction.Reset:
+ {
+ var generator = ItemContainerGenerator;
+ var containers = generator.Containers.ToList();
+ generator.Clear();
+ Panel.Children.RemoveAll(containers.Select(x => x.ContainerControl));
+
+ MoveToPage(-1, SelectedIndex >= 0 ? SelectedIndex : 0);
+ }
+ break;
}
}
diff --git a/tests/Avalonia.Controls.UnitTests/CarouselTests.cs b/tests/Avalonia.Controls.UnitTests/CarouselTests.cs
index 4d38ec9856..df61698209 100644
--- a/tests/Avalonia.Controls.UnitTests/CarouselTests.cs
+++ b/tests/Avalonia.Controls.UnitTests/CarouselTests.cs
@@ -1,11 +1,13 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
+using System.Collections.ObjectModel;
using System.Linq;
using Avalonia.Controls.Presenters;
using Avalonia.Controls.Primitives;
using Avalonia.Controls.Templates;
using Avalonia.LogicalTree;
+using Avalonia.VisualTree;
using Xunit;
namespace Avalonia.Controls.UnitTests
@@ -50,7 +52,7 @@ namespace Avalonia.Controls.UnitTests
Assert.Single(target.GetLogicalChildren());
var child = target.GetLogicalChildren().Single();
-
+
Assert.IsType(child);
Assert.Equal("Foo", ((TextBlock)child).Text);
}
@@ -93,6 +95,173 @@ namespace Avalonia.Controls.UnitTests
Assert.Equal(2, target.ItemContainerGenerator.Containers.Count());
}
+ [Fact]
+ public void Selected_Item_Changes_To_First_Item_When_Items_Property_Changes()
+ {
+ var items = new ObservableCollection
+ {
+ "Foo",
+ "Bar",
+ "FooBar"
+ };
+
+ var target = new Carousel
+ {
+ Template = new FuncControlTemplate(CreateTemplate),
+ Items = items,
+ IsVirtualized = false
+ };
+
+ target.ApplyTemplate();
+ target.Presenter.ApplyTemplate();
+
+ Assert.Single(target.GetLogicalChildren());
+
+ var child = target.GetLogicalChildren().Single();
+
+ Assert.IsType(child);
+ Assert.Equal("Foo", ((TextBlock)child).Text);
+
+ var newItems = items.ToList();
+ newItems.RemoveAt(0);
+
+ target.Items = newItems;
+
+ child = target.GetLogicalChildren().Single();
+
+ Assert.IsType(child);
+ Assert.Equal("Bar", ((TextBlock)child).Text);
+ }
+
+ [Fact]
+ public void Selected_Item_Changes_To_First_Item_When_Items_Property_Changes_And_Virtualized()
+ {
+ var items = new ObservableCollection
+ {
+ "Foo",
+ "Bar",
+ "FooBar"
+ };
+
+ var target = new Carousel
+ {
+ Template = new FuncControlTemplate(CreateTemplate),
+ Items = items
+ };
+
+ target.ApplyTemplate();
+ target.Presenter.ApplyTemplate();
+
+ Assert.Single(target.GetLogicalChildren());
+
+ var child = target.GetLogicalChildren().Single();
+
+ Assert.IsType(child);
+ Assert.Equal("Foo", ((TextBlock)child).Text);
+
+ var newItems = items.ToList();
+ newItems.RemoveAt(0);
+
+ target.Items = newItems;
+
+ child = target.GetLogicalChildren().Single();
+
+ Assert.IsType(child);
+ Assert.Equal("Bar", ((TextBlock)child).Text);
+ }
+
+ [Fact]
+ public void Selected_Index_Is_Maintained_Carousel_Created_With_Non_Zero_SelectedIndex()
+ {
+ var items = new ObservableCollection
+ {
+ "Foo",
+ "Bar",
+ "FooBar"
+ };
+
+ var target = new Carousel
+ {
+ Template = new FuncControlTemplate(CreateTemplate),
+ Items = items,
+ IsVirtualized = false,
+ SelectedIndex = 2
+ };
+
+ target.ApplyTemplate();
+ target.Presenter.ApplyTemplate();
+
+ Assert.Equal("FooBar", target.SelectedItem);
+
+ var child = target.GetVisualDescendants().LastOrDefault();
+
+ Assert.IsType(child);
+ Assert.Equal("FooBar", ((TextBlock)child).Text);
+ }
+
+ [Fact]
+ public void Selected_Item_Changes_To_Next_First_Item_When_Item_Removed_From_Beggining_Of_List()
+ {
+ var items = new ObservableCollection
+ {
+ "Foo",
+ "Bar",
+ "FooBar"
+ };
+
+ var target = new Carousel
+ {
+ Template = new FuncControlTemplate(CreateTemplate),
+ Items = items,
+ IsVirtualized = false
+ };
+
+ target.ApplyTemplate();
+ target.Presenter.ApplyTemplate();
+
+ Assert.Single(target.GetLogicalChildren());
+
+ var child = target.GetLogicalChildren().Single();
+
+ Assert.IsType(child);
+ Assert.Equal("Foo", ((TextBlock)child).Text);
+
+ items.RemoveAt(0);
+
+ child = target.GetLogicalChildren().Single();
+
+ Assert.IsType(child);
+ Assert.Equal("Bar", ((TextBlock)child).Text);
+ }
+
+ [Fact]
+ public void Selected_Item_Changes_To_NextAvailable_Item_If_SelectedItem_Is_Removed_From_Middle()
+ {
+ var items = new ObservableCollection
+ {
+ "Foo",
+ "Bar",
+ "FooBar"
+ };
+
+ var target = new Carousel
+ {
+ Template = new FuncControlTemplate(CreateTemplate),
+ Items = items,
+ IsVirtualized = false
+ };
+
+ target.ApplyTemplate();
+ target.Presenter.ApplyTemplate();
+
+ target.SelectedIndex = 1;
+
+ items.RemoveAt(1);
+
+ Assert.Equal(1, target.SelectedIndex);
+ Assert.Equal("FooBar", target.SelectedItem);
+ }
+
private Control CreateTemplate(Carousel control)
{
return new CarouselPresenter