diff --git a/components/Carousel/OpenSolution.bat b/components/Carousel/OpenSolution.bat
new file mode 100644
index 00000000..814a56d4
--- /dev/null
+++ b/components/Carousel/OpenSolution.bat
@@ -0,0 +1,3 @@
+@ECHO OFF
+
+powershell ..\..\tooling\ProjectHeads\GenerateSingleSampleHeads.ps1 -componentPath %CD% %*
\ No newline at end of file
diff --git a/components/Carousel/samples/Assets/icon.png b/components/Carousel/samples/Assets/icon.png
new file mode 100644
index 00000000..8435bcaa
Binary files /dev/null and b/components/Carousel/samples/Assets/icon.png differ
diff --git a/components/Carousel/samples/Carousel.Samples.csproj b/components/Carousel/samples/Carousel.Samples.csproj
new file mode 100644
index 00000000..7b4d6dd9
--- /dev/null
+++ b/components/Carousel/samples/Carousel.Samples.csproj
@@ -0,0 +1,10 @@
+
+
+
+
+ Carousel
+
+
+
+
+
diff --git a/components/Carousel/samples/Carousel.md b/components/Carousel/samples/Carousel.md
new file mode 100644
index 00000000..070c8677
--- /dev/null
+++ b/components/Carousel/samples/Carousel.md
@@ -0,0 +1,65 @@
+---
+title: Carousel
+author: githubaccount
+description: TODO: Your experiment's description here
+keywords: Carousel, Control, Layout
+dev_langs:
+ - csharp
+category: Controls
+subcategory: Layout
+discussion-id: 0
+issue-id: 0
+icon: assets/icon.png
+---
+
+
+
+
+
+
+
+
+
+# Carousel
+
+TODO: Fill in information about this experiment and how to get started here...
+
+## Custom Control
+
+You can inherit from an existing component as well, like `Panel`, this example shows a control without a
+XAML Style that will be more light-weight to consume by an app developer:
+
+> [!Sample CarouselCustomSample]
+
+## Templated Controls
+
+The Toolkit is built with templated controls. This provides developers a flexible way to restyle components
+easily while still inheriting the general functionality a control provides. The examples below show
+how a component can use a default style and then get overridden by the end developer.
+
+TODO: Two types of templated control building methods are shown. Delete these if you're building a custom component.
+Otherwise, pick one method for your component and delete the files related to the unchosen `_ClassicBinding` or `_xBind`
+classes (and the custom non-suffixed one as well). Then, rename your component to just be your component name.
+
+The `_ClassicBinding` class shows the traditional method used to develop components with best practices.
+
+### Implict style
+
+> [!SAMPLE CarouselTemplatedSample]
+
+### Custom style
+
+> [!SAMPLE CarouselTemplatedStyleCustomSample]
+
+## Templated Controls with x:Bind
+
+This is an _experimental_ new way to define components which allows for the use of x:Bind within the style.
+
+### Implict style
+
+> [!SAMPLE CarouselXbindBackedSample]
+
+### Custom style
+
+> [!SAMPLE CarouselXbindBackedStyleCustomSample]
+
diff --git a/components/Carousel/samples/CarouselCustomSample.xaml b/components/Carousel/samples/CarouselCustomSample.xaml
new file mode 100644
index 00000000..392e630e
--- /dev/null
+++ b/components/Carousel/samples/CarouselCustomSample.xaml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/components/Carousel/samples/CarouselCustomSample.xaml.cs b/components/Carousel/samples/CarouselCustomSample.xaml.cs
new file mode 100644
index 00000000..c70ff312
--- /dev/null
+++ b/components/Carousel/samples/CarouselCustomSample.xaml.cs
@@ -0,0 +1,30 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using CommunityToolkit.WinUI.Controls;
+
+namespace CarouselExperiment.Samples;
+
+///
+/// An example sample page of a custom control inheriting from Panel.
+///
+[ToolkitSampleTextOption("TitleText", "This is a title", Title = "Input the text")]
+[ToolkitSampleMultiChoiceOption("LayoutOrientation", "Horizontal", "Vertical", Title = "Orientation")]
+
+[ToolkitSample(id: nameof(CarouselCustomSample), "Custom control", description: $"A sample for showing how to create and use a {nameof(Carousel)} custom control.")]
+public sealed partial class CarouselCustomSample : Page
+{
+ public CarouselCustomSample()
+ {
+ this.InitializeComponent();
+ }
+
+ // TODO: See https://github.com/CommunityToolkit/Labs-Windows/issues/149
+ public static Orientation ConvertStringToOrientation(string orientation) => orientation switch
+ {
+ "Vertical" => Orientation.Vertical,
+ "Horizontal" => Orientation.Horizontal,
+ _ => throw new System.NotImplementedException(),
+ };
+}
diff --git a/components/Carousel/samples/CarouselTemplatedSample.xaml b/components/Carousel/samples/CarouselTemplatedSample.xaml
new file mode 100644
index 00000000..70ded607
--- /dev/null
+++ b/components/Carousel/samples/CarouselTemplatedSample.xaml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
diff --git a/components/Carousel/samples/CarouselTemplatedSample.xaml.cs b/components/Carousel/samples/CarouselTemplatedSample.xaml.cs
new file mode 100644
index 00000000..86f32c20
--- /dev/null
+++ b/components/Carousel/samples/CarouselTemplatedSample.xaml.cs
@@ -0,0 +1,21 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace CarouselExperiment.Samples;
+
+[ToolkitSampleBoolOption("IsTextVisible", true, Title = "IsVisible")]
+// Single values without a colon are used for both label and value.
+// To provide a different label for the value, separate with a colon surrounded by a single space on both sides ("label : value").
+[ToolkitSampleNumericOption("TextSize", 12, 8, 48, 2, false, Title = "FontSize")]
+[ToolkitSampleMultiChoiceOption("TextFontFamily", "Segoe UI", "Arial", "Consolas", Title = "Font family")]
+[ToolkitSampleMultiChoiceOption("TextForeground", "Teal : #0ddc8c", "Sand : #e7a676", "Dull green : #5d7577", Title = "Text foreground")]
+
+[ToolkitSample(id: nameof(CarouselTemplatedSample), "Templated control", description: "A sample for showing how to create and use a templated control.")]
+public sealed partial class CarouselTemplatedSample : Page
+{
+ public CarouselTemplatedSample()
+ {
+ this.InitializeComponent();
+ }
+}
diff --git a/components/Carousel/samples/CarouselTemplatedStyleCustomSample.xaml b/components/Carousel/samples/CarouselTemplatedStyleCustomSample.xaml
new file mode 100644
index 00000000..08dff9a7
--- /dev/null
+++ b/components/Carousel/samples/CarouselTemplatedStyleCustomSample.xaml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/components/Carousel/samples/CarouselTemplatedStyleCustomSample.xaml.cs b/components/Carousel/samples/CarouselTemplatedStyleCustomSample.xaml.cs
new file mode 100644
index 00000000..3fc9960b
--- /dev/null
+++ b/components/Carousel/samples/CarouselTemplatedStyleCustomSample.xaml.cs
@@ -0,0 +1,21 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace CarouselExperiment.Samples;
+
+[ToolkitSampleBoolOption("IsTextVisible", true, Title = "IsVisible")]
+// Single values without a colon are used for both label and value.
+// To provide a different label for the value, separate with a colon surrounded by a single space on both sides ("label : value").
+[ToolkitSampleNumericOption("TextSize", 12, 8, 48, 2, true, Title = "FontSize")]
+[ToolkitSampleMultiChoiceOption("TextFontFamily", "Segoe UI", "Arial", "Consolas", Title = "Font family")]
+[ToolkitSampleMultiChoiceOption("TextForeground", "Teal : #0ddc8c", "Sand : #e7a676", "Dull green : #5d7577", Title = "Text foreground")]
+
+[ToolkitSample(id: nameof(CarouselTemplatedStyleCustomSample), "Templated control (restyled)", description: "A sample for showing how to create a use and templated control with a custom style.")]
+public sealed partial class CarouselTemplatedStyleCustomSample : Page
+{
+ public CarouselTemplatedStyleCustomSample()
+ {
+ this.InitializeComponent();
+ }
+}
diff --git a/components/Carousel/samples/CarouselXbindBackedSample.xaml b/components/Carousel/samples/CarouselXbindBackedSample.xaml
new file mode 100644
index 00000000..1c195009
--- /dev/null
+++ b/components/Carousel/samples/CarouselXbindBackedSample.xaml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
diff --git a/components/Carousel/samples/CarouselXbindBackedSample.xaml.cs b/components/Carousel/samples/CarouselXbindBackedSample.xaml.cs
new file mode 100644
index 00000000..a3d9c35a
--- /dev/null
+++ b/components/Carousel/samples/CarouselXbindBackedSample.xaml.cs
@@ -0,0 +1,21 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace CarouselExperiment.Samples;
+
+[ToolkitSampleBoolOption("IsTextVisible", true, Title = "IsVisible")]
+// Single values without a colon are used for both label and value.
+// To provide a different label for the value, separate with a colon surrounded by a single space on both sides ("label : value").
+[ToolkitSampleNumericOption("TextSize", 12, 8, 48, 2, false, Title = "FontSize")]
+[ToolkitSampleMultiChoiceOption("TextFontFamily", "Segoe UI", "Arial", "Consolas", Title = "Font family")]
+[ToolkitSampleMultiChoiceOption("TextForeground", "Teal : #0ddc8c", "Sand : #e7a676", "Dull green : #5d7577", Title = "Text foreground")]
+
+[ToolkitSample(id: nameof(CarouselXbindBackedSample), "Backed templated control", description: "A sample for showing how to create and use a templated control with a backed resource dictionary.")]
+public sealed partial class CarouselXbindBackedSample : Page
+{
+ public CarouselXbindBackedSample()
+ {
+ this.InitializeComponent();
+ }
+}
diff --git a/components/Carousel/samples/CarouselXbindBackedStyleCustomSample.xaml b/components/Carousel/samples/CarouselXbindBackedStyleCustomSample.xaml
new file mode 100644
index 00000000..d860f3dd
--- /dev/null
+++ b/components/Carousel/samples/CarouselXbindBackedStyleCustomSample.xaml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/components/Carousel/samples/CarouselXbindBackedStyleCustomSample.xaml.cs b/components/Carousel/samples/CarouselXbindBackedStyleCustomSample.xaml.cs
new file mode 100644
index 00000000..6123f44a
--- /dev/null
+++ b/components/Carousel/samples/CarouselXbindBackedStyleCustomSample.xaml.cs
@@ -0,0 +1,21 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace CarouselExperiment.Samples;
+
+[ToolkitSampleBoolOption("IsTextVisible", true, Title = "IsVisible")]
+// Single values without a colon are used for both label and value.
+// To provide a different label for the value, separate with a colon surrounded by a single space on both sides ("label : value").
+[ToolkitSampleNumericOption("TextSize", 12, 8, 48, 2, true, Title = "FontSize")]
+[ToolkitSampleMultiChoiceOption("TextFontFamily", "Segoe UI", "Arial", "Consolas", Title = "Font family")]
+[ToolkitSampleMultiChoiceOption("TextForeground", "Teal : #0ddc8c", "Sand : #e7a676", "Dull green : #5d7577", Title = "Text foreground")]
+
+[ToolkitSample(id: nameof(CarouselXbindBackedStyleCustomSample), "Backed templated control (restyled)", description: "A sample for showing how to create and use a templated control with a backed resource dictionary and a custom style.")]
+public sealed partial class CarouselXbindBackedStyleCustomSample : Page
+{
+ public CarouselXbindBackedStyleCustomSample()
+ {
+ this.InitializeComponent();
+ }
+}
diff --git a/components/Carousel/samples/Dependencies.props b/components/Carousel/samples/Dependencies.props
new file mode 100644
index 00000000..e622e1df
--- /dev/null
+++ b/components/Carousel/samples/Dependencies.props
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/components/Carousel/src/Carousel.Properties.cs b/components/Carousel/src/Carousel.Properties.cs
new file mode 100644
index 00000000..99ace3e9
--- /dev/null
+++ b/components/Carousel/src/Carousel.Properties.cs
@@ -0,0 +1,151 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Numerics;
+
+namespace CommunityToolkit.WinUI.Controls;
+
+public partial class Carousel
+{
+ ///
+ /// The backing for the property.
+ ///
+ public static readonly DependencyProperty OrientationProperty =
+ DependencyProperty.Register(nameof(Orientation), typeof(Orientation), typeof(Carousel), new PropertyMetadata(Orientation.Horizontal));
+
+ ///
+ /// The backing for the property.
+ ///
+ public static readonly DependencyProperty SelectedIndexProperty =
+ DependencyProperty.Register(nameof(SelectedIndex), typeof(int), typeof(Carousel), new PropertyMetadata(-1, OnCarouselSelectionPropertyChanged));
+
+ ///
+ /// The backing for the property.
+ ///
+ public static readonly DependencyProperty SelectedItemProperty =
+ DependencyProperty.Register(nameof(SelectedItem), typeof(object), typeof(Carousel), new PropertyMetadata(null, OnCarouselSelectionPropertyChanged));
+
+ ///
+ /// The backing for the property.
+ ///
+ public static readonly DependencyProperty ItemSpacingProperty =
+ DependencyProperty.Register(nameof(ItemSpacing), typeof(double), typeof(Carousel), new PropertyMetadata(0));
+
+ ///
+ /// The backing for the property.
+ ///
+ public static readonly DependencyProperty TransitionDurationProperty =
+ DependencyProperty.Register(nameof(TransitionDuration), typeof(TimeSpan), typeof(Carousel), new PropertyMetadata(TimeSpan.FromMilliseconds(200)));
+
+ ///
+ /// The backing for the property.
+ ///
+ public static readonly DependencyProperty EasingFunctionProperty =
+ DependencyProperty.Register(nameof(TransitionDuration), typeof(EasingFunctionBase), typeof(Carousel), new PropertyMetadata(null));
+
+ ///
+ /// The backing for the property.
+ ///
+ public static readonly DependencyProperty ItemDepthProperty =
+ DependencyProperty.Register(nameof(ItemDepth), typeof(double), typeof(Carousel), new PropertyMetadata(0));
+
+ ///
+ /// The backing for the property.
+ ///
+ public static readonly DependencyProperty ItemRotationProperty =
+ DependencyProperty.Register(nameof(ItemRotation), typeof(double), typeof(Carousel), new PropertyMetadata(Vector3.Zero));
+
+ ///
+ /// The backing for the property.
+ ///
+ public static readonly DependencyProperty InvertPositiveProperty =
+ DependencyProperty.Register(nameof(InvertPositive), typeof(bool), typeof(Carousel), new PropertyMetadata(true));
+
+ ///
+ /// Gets or sets the orientation to render items.
+ ///
+ public Orientation Orientation
+ {
+ get => (Orientation)GetValue(OrientationProperty);
+ set => SetValue(OrientationProperty, value);
+ }
+
+ ///
+ /// Gets or sets the index of the selected item.
+ ///
+ public int SelectedIndex
+ {
+ get => (int)GetValue(SelectedIndexProperty);
+ set => SetValue(SelectedIndexProperty, value);
+ }
+
+ ///
+ /// Gets or sets the selected item.
+ ///
+ public object? SelectedItem
+ {
+ get => (object?)GetValue(SelectedItemProperty);
+ set => SetValue(SelectedItemProperty, value);
+ }
+
+ ///
+ /// Gets or sets the selected item.
+ ///
+ public double? ItemSpacing
+ {
+ get => (double?)GetValue(ItemSpacingProperty);
+ set => SetValue(ItemSpacingProperty, value);
+ }
+
+ ///
+ /// Gets or sets the transition animation duration.
+ ///
+ public TimeSpan TransitionDuration
+ {
+ get => (TimeSpan)GetValue(TransitionDurationProperty);
+ set => SetValue(TransitionDurationProperty, value);
+ }
+
+ ///
+ /// Gets or sets the transition animation duration.
+ ///
+ public EasingFunctionBase? EasingFunction
+ {
+ get => (EasingFunctionBase?)GetValue(EasingFunctionProperty);
+ set => SetValue(EasingFunctionProperty, value);
+ }
+
+ ///
+ /// Gets or sets the depth for unselected items.
+ ///
+ public double ItemDepth
+ {
+ get => (double)GetValue(TransitionDurationProperty);
+ set => SetValue(TransitionDurationProperty, value);
+ }
+
+ ///
+ /// Gets or sets the rotation to apply to carousel items.
+ ///
+ public Vector3 ItemRotation
+ {
+ get => (Vector3)GetValue(ItemRotationProperty);
+ set => SetValue(ItemRotationProperty, value);
+ }
+
+ ///
+ /// Gets or sets the rotation to apply to carousel items.
+ ///
+ public bool InvertPositive
+ {
+ get => (bool)GetValue(InvertPositiveProperty);
+ set => SetValue(InvertPositiveProperty, value);
+ }
+
+ private static void OnCarouselSelectionPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ if (d is not Carousel carousel)
+ return;
+ }
+}
diff --git a/components/Carousel/src/Carousel.cs b/components/Carousel/src/Carousel.cs
new file mode 100644
index 00000000..7160f8d3
--- /dev/null
+++ b/components/Carousel/src/Carousel.cs
@@ -0,0 +1,31 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace CommunityToolkit.WinUI.Controls;
+
+///
+/// An example templated control.
+///
+public partial class Carousel : ItemsControl
+{
+ ///
+ /// Occurs when the selected item changes.
+ ///
+ public event SelectionChangedEventHandler? SelectionChanged;
+
+ ///
+ /// Creates a new instance of the class.
+ ///
+ public Carousel()
+ {
+ this.DefaultStyleKey = typeof(Carousel);
+ }
+
+ ///
+ /// Returns the container used for each item
+ ///
+ /// Returns always a CarouselItem
+ protected override DependencyObject GetContainerForItemOverride()
+ => new CarouselItem();
+}
diff --git a/components/Carousel/src/CarouselItem.cs b/components/Carousel/src/CarouselItem.cs
new file mode 100644
index 00000000..b2689f45
--- /dev/null
+++ b/components/Carousel/src/CarouselItem.cs
@@ -0,0 +1,72 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace CommunityToolkit.WinUI.Controls;
+
+///
+/// Represents the container for an item in a control
+///
+public partial class CarouselItem : SelectorItem
+{
+ private const string PointerOverState = "PointerOver";
+ private const string PointerOverSelectedState = "PointerOverSelected";
+ private const string PressedState = "Pressed";
+ private const string PressedSelectedState = "PressedSelected";
+ private const string SelectedState = "Selected";
+ private const string NormalState = "Normal";
+
+ ///
+ /// Fired when the is selected.
+ ///
+ public event EventHandler? Selected;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public CarouselItem()
+ {
+ DefaultStyleKey = typeof(CarouselItem);
+
+ RegisterPropertyChangedCallback(IsSelectedProperty, OnIsSelectedChanged);
+ }
+
+ ///
+ protected override void OnPointerEntered(PointerRoutedEventArgs e)
+ {
+ base.OnPointerEntered(e);
+
+ VisualStateManager.GoToState(this, IsSelected ? PointerOverSelectedState : PointerOverState, true);
+ }
+
+ ///
+ protected override void OnPointerExited(PointerRoutedEventArgs e)
+ {
+ base.OnPointerExited(e);
+
+ VisualStateManager.GoToState(this, IsSelected ? SelectedState : NormalState, true);
+ }
+
+ ///
+ protected override void OnPointerPressed(PointerRoutedEventArgs e)
+ {
+ base.OnPointerPressed(e);
+
+ VisualStateManager.GoToState(this, IsSelected ? PressedSelectedState : PressedState, true);
+ }
+
+ private void OnIsSelectedChanged(DependencyObject sender, DependencyProperty dp)
+ {
+ var item = (CarouselItem)sender;
+
+ if (item.IsSelected)
+ {
+ Selected?.Invoke(this, EventArgs.Empty);
+ VisualStateManager.GoToState(item, SelectedState, true);
+ }
+ else
+ {
+ VisualStateManager.GoToState(item, NormalState, true);
+ }
+ }
+}
diff --git a/components/Carousel/src/CarouselStyle.xaml b/components/Carousel/src/CarouselStyle.xaml
new file mode 100644
index 00000000..61d2b81d
--- /dev/null
+++ b/components/Carousel/src/CarouselStyle.xaml
@@ -0,0 +1,66 @@
+
+
+
+
+
+
+
+
diff --git a/components/Carousel/src/CommunityToolkit.WinUI.Controls.Carousel.csproj b/components/Carousel/src/CommunityToolkit.WinUI.Controls.Carousel.csproj
new file mode 100644
index 00000000..84430ea1
--- /dev/null
+++ b/components/Carousel/src/CommunityToolkit.WinUI.Controls.Carousel.csproj
@@ -0,0 +1,14 @@
+
+
+
+
+ Carousel
+ This package contains Carousel.
+
+
+ CommunityToolkit.WinUI.Controls.CarouselRns
+
+
+
+
+
diff --git a/components/Carousel/src/Dependencies.props b/components/Carousel/src/Dependencies.props
new file mode 100644
index 00000000..e622e1df
--- /dev/null
+++ b/components/Carousel/src/Dependencies.props
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/components/Carousel/src/MultiTarget.props b/components/Carousel/src/MultiTarget.props
new file mode 100644
index 00000000..b11c1942
--- /dev/null
+++ b/components/Carousel/src/MultiTarget.props
@@ -0,0 +1,9 @@
+
+
+
+ uwp;wasdk;wpf;wasm;linuxgtk;macos;ios;android;
+
+
\ No newline at end of file
diff --git a/components/Carousel/src/Themes/Generic.xaml b/components/Carousel/src/Themes/Generic.xaml
new file mode 100644
index 00000000..301137bb
--- /dev/null
+++ b/components/Carousel/src/Themes/Generic.xaml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
diff --git a/components/Carousel/tests/Carousel.Tests.projitems b/components/Carousel/tests/Carousel.Tests.projitems
new file mode 100644
index 00000000..378417eb
--- /dev/null
+++ b/components/Carousel/tests/Carousel.Tests.projitems
@@ -0,0 +1,23 @@
+
+
+
+ $(MSBuildAllProjects);$(MSBuildThisFileFullPath)
+ true
+ 4FFF589B-BBD2-47F1-A5D6-0568F4801D79
+
+
+ CarouselTests
+
+
+
+
+ ExampleCarouselTestPage.xaml
+
+
+
+
+ Designer
+ MSBuild:Compile
+
+
+
\ No newline at end of file
diff --git a/components/Carousel/tests/Carousel.Tests.shproj b/components/Carousel/tests/Carousel.Tests.shproj
new file mode 100644
index 00000000..8ad0ea28
--- /dev/null
+++ b/components/Carousel/tests/Carousel.Tests.shproj
@@ -0,0 +1,13 @@
+
+
+
+ 4FFF589B-BBD2-47F1-A5D6-0568F4801D79
+ 14.0
+
+
+
+
+
+
+
+
diff --git a/components/Carousel/tests/ExampleCarouselTestClass.cs b/components/Carousel/tests/ExampleCarouselTestClass.cs
new file mode 100644
index 00000000..cc205524
--- /dev/null
+++ b/components/Carousel/tests/ExampleCarouselTestClass.cs
@@ -0,0 +1,134 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using CommunityToolkit.Tooling.TestGen;
+using CommunityToolkit.Tests;
+using CommunityToolkit.WinUI.Controls;
+
+namespace CarouselTests;
+
+[TestClass]
+public partial class ExampleCarouselTestClass : VisualUITestBase
+{
+ // If you don't need access to UI objects directly or async code, use this pattern.
+ [TestMethod]
+ public void SimpleSynchronousExampleTest()
+ {
+ var assembly = typeof(Carousel).Assembly;
+ var type = assembly.GetType(typeof(Carousel).FullName ?? string.Empty);
+
+ Assert.IsNotNull(type, "Could not find Carousel type.");
+ Assert.AreEqual(typeof(Carousel), type, "Type of Carousel does not match expected type.");
+ }
+
+ // If you don't need access to UI objects directly, use this pattern.
+ [TestMethod]
+ public async Task SimpleAsyncExampleTest()
+ {
+ await Task.Delay(250);
+
+ Assert.IsTrue(true);
+ }
+
+ // Example that shows how to check for exception throwing.
+ [TestMethod]
+ public void SimpleExceptionCheckTest()
+ {
+ // If you need to check exceptions occur for invalid inputs, etc...
+ // Use Assert.ThrowsException to limit the scope to where you expect the error to occur.
+ // Otherwise, using the ExpectedException attribute could swallow or
+ // catch other issues in setup code.
+ Assert.ThrowsException(() => throw new NotImplementedException());
+ }
+
+ // The UIThreadTestMethod automatically dispatches to the UI for us to work with UI objects.
+ [UIThreadTestMethod]
+ public void SimpleUIAttributeExampleTest()
+ {
+ var component = new Carousel();
+ Assert.IsNotNull(component);
+ }
+
+ // The UIThreadTestMethod can also easily grab a XAML Page for us by passing its type as a parameter.
+ // This lets us actually test a control as it would behave within an actual application.
+ // The page will already be loaded by the time your test is called.
+ [UIThreadTestMethod]
+ public void SimpleUIExamplePageTest(ExampleCarouselTestPage page)
+ {
+ // You can use the Toolkit Visual Tree helpers here to find the component by type or name:
+ var component = page.FindDescendant();
+
+ Assert.IsNotNull(component);
+
+ var componentByName = page.FindDescendant("CarouselControl");
+
+ Assert.IsNotNull(componentByName);
+ }
+
+ // You can still do async work with a UIThreadTestMethod as well.
+ [UIThreadTestMethod]
+ public async Task SimpleAsyncUIExamplePageTest(ExampleCarouselTestPage page)
+ {
+ // This helper can be used to wait for a rendering pass to complete.
+ // Note, this is already done by loading a Page with the [UIThreadTestMethod] helper.
+ await CompositionTargetHelper.ExecuteAfterCompositionRenderingAsync(() => { });
+
+ var component = page.FindDescendant();
+
+ Assert.IsNotNull(component);
+ }
+
+ //// ----------------------------- ADVANCED TEST SCENARIOS -----------------------------
+
+ // If you need to use DataRow, you can use this pattern with the UI dispatch still.
+ // Otherwise, checkout the UIThreadTestMethod attribute above.
+ // See https://github.com/CommunityToolkit/Labs-Windows/issues/186
+ [TestMethod]
+ public async Task ComplexAsyncUIExampleTest()
+ {
+ await EnqueueAsync(() =>
+ {
+ var component = new Carousel();
+ Assert.IsNotNull(component);
+ });
+ }
+
+ // If you want to load other content not within a XAML page using the UIThreadTestMethod above.
+ // Then you can do that using the Load/UnloadTestContentAsync methods.
+ [TestMethod]
+ public async Task ComplexAsyncLoadUIExampleTest()
+ {
+ await EnqueueAsync(async () =>
+ {
+ var component = new Carousel();
+ Assert.IsNotNull(component);
+ Assert.IsFalse(component.IsLoaded);
+
+ await LoadTestContentAsync(component);
+
+ Assert.IsTrue(component.IsLoaded);
+
+ await UnloadTestContentAsync(component);
+
+ Assert.IsFalse(component.IsLoaded);
+ });
+ }
+
+ // You can still use the UIThreadTestMethod to remove the extra layer for the dispatcher as well:
+ [UIThreadTestMethod]
+ public async Task ComplexAsyncLoadUIExampleWithoutDispatcherTest()
+ {
+ var component = new Carousel();
+ Assert.IsNotNull(component);
+ Assert.IsFalse(component.IsLoaded);
+
+ await LoadTestContentAsync(component);
+
+ Assert.IsTrue(component.IsLoaded);
+
+ await UnloadTestContentAsync(component);
+
+ Assert.IsFalse(component.IsLoaded);
+ }
+}
diff --git a/components/Carousel/tests/ExampleCarouselTestPage.xaml b/components/Carousel/tests/ExampleCarouselTestPage.xaml
new file mode 100644
index 00000000..86719c0f
--- /dev/null
+++ b/components/Carousel/tests/ExampleCarouselTestPage.xaml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
diff --git a/components/Carousel/tests/ExampleCarouselTestPage.xaml.cs b/components/Carousel/tests/ExampleCarouselTestPage.xaml.cs
new file mode 100644
index 00000000..766077ea
--- /dev/null
+++ b/components/Carousel/tests/ExampleCarouselTestPage.xaml.cs
@@ -0,0 +1,16 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace CarouselTests;
+
+///
+/// An empty page that can be used on its own or navigated to within a Frame.
+///
+public sealed partial class ExampleCarouselTestPage : Page
+{
+ public ExampleCarouselTestPage()
+ {
+ this.InitializeComponent();
+ }
+}