Carousel is an item host with prev/next chevrons, dot indicators, and ArrowLeft/ArrowRight
keyboard navigation. It derives Selector directly (the same WPF base ListBox/TabControl
use) rather than a bespoke “current index” property, so it gets SelectedIndex/SelectedItem
as bindable dependency properties for free; the template’s ItemContainerStyle uses
Selector.IsSelected to show only the current slide, cross-faded, and to light the matching dot.
Slides are added directly as UIElement items (each item is its own container). Pointer-swipe
physics are explicitly out of scope; only the chevrons, dots, and keyboard arrows drive
navigation.
Whether Next from the last slide wraps to the first (and Previous from the first wraps to the last).
Items
ItemCollection
empty
ItemsControl (via Selector)
Populated directly with UIElement slides; each item is its own container (IsItemItsOwnContainerOverride returns true for UIElement).
SelectedIndex
int
-1
Selector
Bindable current-slide index. Auto-initializes to 0 the first time items appear (an empty carousel with slides and nothing selected would read as broken).
NaviusCarousel does not override OnCreateAutomationPeer, and Selector itself does not
supply one either (only concrete selector controls like ListBox do), so the control falls back
to ItemsControl’s peer, ItemsControlAutomationPeer, reporting AutomationControlType.List.
The unit suite exercises CarouselEngine.MoveIndex (the pure index-wrap math backing both
Loop directions and the no-loop clamp), default Loop/SelectedIndex values, auto-selection
of the first slide once items are added, and GoToSlideCommand selection
(tests/Navius.Wpf.Tests/UiCompositeTests.cs).
Pointer-swipe physics are explicitly out of scope for this control; only the chevrons, dots,
and keyboard arrows drive navigation, unlike touch/pointer-swipe carousels on the web.
Known residual (M6 audit): the slide crossfade storyboards (two 0.15s opacity DoubleAnimations
in the container’s EnterActions/ExitActions) have no reduced-motion guard. Gating them would
require adding a new ShouldAnimate dependency property and rewiring the triggers, which the
audit judged to exceed a surgical fix; the fade is a one-shot 150ms crossfade rather than one of
the endless loops the ReducedMotion seam targets, and no doc comment claims otherwise. Recorded
for a follow-up if the discipline is tightened to cover transient transitions.