HypernovaDesktop Components · docs
Binarymission
WPF › Carousel › Carousel

Carousel

class.NET 6 / 8 / 10.NET Framework 4.8Binarymission.WPF.Controls.Containers

A 3D carousel: the items stand round a circle in perspective, and the selected one turns to face the viewer at the front, the others angled away behind it.

public partial class Carousel : ItemsControl

Inherits from / implements: ItemsControl

Remarks

Use it to browse a modest set of visual items one at a time – product photographs, album or book covers, a portfolio, the screens of a kiosk, the templates in a "new document" gallery. It is an ItemsControl, so the items can be anything: bind ItemsControl.ItemsSource to your data and describe each item with an ItemsControl.ItemTemplate, or add elements to ItemsControl.Items directly.

Selection and navigation

SelectedIndex is the item at the front. Set it, or bind it, to a valid index – it starts at -1, where no item has been brought forward and the items are not yet arranged round the circle. The user moves the selection by clicking an item, turning the mouse wheel, or pressing the Left and Right arrow keys (the MoveToLeft and MoveToRight commands, which buttons of your own can use too). Each move turns the carousel in half a second, and SelectedIndexChanged follows.

Items

Each item is drawn at ItemDimension – 300 by 250 logical pixels by default – and then shown in 3D, so that size decides its shape and how sharp it is rather than how large it appears. For a list of image paths, the template keyed CarouselControlResources.CarouselItemTemplateKey shows each picture in a white frame. IsReflectionRenderingEnabled adds a mirror-image reflection beneath every item.

Shape of the ring

GapBetweenItems spaces the items round the circle, and with it the circle's size; ItemRenderAngle turns the items that are not at the front; DistanceFromCentreToUser brings the front item towards the viewer, and GapBetweenCurrentDisplayFrontItemAndOthers pushes the rest back. The view is set by Camera (or CarouselViewport3DCamera) and lit by CarouselViewport3DAmbientLightColor. All lengths in 3D are in model units, in which an item is one unit tall.

Examples

A product gallery in XAML: the window's data context exposes ProductImages, a list of image paths, and CurrentProduct, the index of the product on show.

<Window x:Class="Shop.GalleryWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:car="clr-namespace:Binarymission.WPF.Controls.Containers;assembly=Binarymission.WPF.Controls.Carousel"
        xmlns:carRes="clr-namespace:Binarymission.WPF.Controls.Containers.SharedResources;assembly=Binarymission.WPF.Controls.Carousel"
        Title="Spring collection" Width="900" Height="520">

    <DockPanel Background="#20242B">
        <StackPanel DockPanel.Dock="Bottom" Orientation="Horizontal" HorizontalAlignment="Center" Margin="12">
            <Button Content="Previous" Margin="4" Command="{x:Static car:Carousel.MoveToLeft}"  CommandTarget="{Binding ElementName=Gallery}" />
            <Button Content="Next"     Margin="4" Command="{x:Static car:Carousel.MoveToRight}" CommandTarget="{Binding ElementName=Gallery}" />
        </StackPanel>

        <car:Carousel x:Name="Gallery"
                      ItemsSource="{Binding ProductImages}"
                      SelectedIndex="{Binding CurrentProduct}"
                      ItemTemplate="{DynamicResource {x:Static carRes:CarouselControlResources.CarouselItemTemplateKey}}"
                      ItemDimension="320,240"
                      IsReflectionRenderingEnabled="True"
                      ItemRenderAngle="40"
                      GapBetweenItems="0.6" />
    </DockPanel>
</Window>

The same carousel filled with elements from code, reacting as the user turns it.

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media.Imaging;
using Binarymission.WPF.Controls.Containers;

Carousel gallery = new Carousel
{
    ItemDimension = new Size(320, 240),
    IsReflectionRenderingEnabled = true
};

foreach (string file in new[] { "chair.jpg", "desk.jpg", "lamp.jpg", "shelf.jpg", "sofa.jpg" })
{
    gallery.Items.Add(new Image { Source = new BitmapImage(new Uri("pack://application:,,,/Products/" + file)), Stretch = System.Windows.Media.Stretch.Uniform });
}

gallery.SelectedIndex = 0;
gallery.SelectedIndexChanged += (sender, e) =>
    statusText.Text = "Product " + (gallery.SelectedIndex + 1) + " of " + gallery.Items.Count;

See also

Members at a glance

Constructors
CarouselCreates an empty carousel, with the arrow-key commands ready and white lighting.
Properties
CameraGets or sets the perspective camera the carousel is viewed through, to change the viewpoint, the distance or the field of view.
CarouselViewport3DAmbientLightColorGets or sets the colour of the light the carousel's items are lit by.
CarouselViewport3DCameraGets or sets the camera the carousel is viewed through, of any kind – for example an OrthographicCamera for a flat view without perspective.
DistanceFromCentreToUserGets or sets how far the item at the front is brought forward, towards the viewer.
GapBetweenCurrentDisplayFrontItemAndOthersGets or sets how far the items that are not at the front are pushed back, away from the viewer.
GapBetweenItemsGets or sets how far apart the items stand round the circle, which also sets the circle's size.
IsReflectionRenderingEnabledGets or sets whether each item is drawn with a mirror-image reflection beneath it, fading to transparent, as though standing on a glossy floor.
ItemDimensionGets or sets the size each item is drawn at before it is placed in 3D, which decides its shape and its sharpness.
ItemRenderAngleGets or sets how far the items that are not at the front are turned away from the viewer.
SelectedIndexGets or sets the position of the item at the front of the carousel, facing the viewer.
VisualChildrenCountGets the number of visual children: one once the template has been applied, otherwise none.
Methods
ClearContainerForItemOverrideTakes an item off the carousel when it is removed, and brings the selection back within the remaining items.
OnApplyTemplateFinds the 3D viewport, the item container and the light in the template, and applies the camera and the light colour to them.
OnMouseWheelTurns the carousel one item for each notch of the mouse wheel, and gives it keyboard focus.
PrepareContainerForItemOverrideSizes an item's container to ItemDimension and puts the item on the carousel.
Events
SelectedIndexChangedOccurs when SelectedIndex changes, whether the user turned the carousel or code set the index.
Fields
CameraPropertyIdentifies the Camera dependency property.
CarouselViewport3DAmbientLightColorPropertyIdentifies the CarouselViewport3DAmbientLightColor dependency property.
CarouselViewport3DCameraPropertyIdentifies the CarouselViewport3DCamera dependency property.
DistanceFromCentreToUserPropertyIdentifies the DistanceFromCentreToUser dependency property.
GapBetweenCurrentDisplayFrontItemAndOthersPropertyIdentifies the GapBetweenCurrentDisplayFrontItemAndOthers dependency property.
GapBetweenItemsPropertyIdentifies the GapBetweenItems dependency property.
IsReflectionRenderingEnabledPropertyIdentifies the IsReflectionRenderingEnabled dependency property.
ItemDimensionPropertyIdentifies the ItemDimension dependency property.
ItemRenderAnglePropertyIdentifies the ItemRenderAngle dependency property.
MoveToLeftThe command that moves the selection to the previous item; bound to the Left arrow key.
MoveToRightThe command that moves the selection to the next item; bound to the Right arrow key.
SelectedIndexPropertyIdentifies the SelectedIndex dependency property.

Constructors

Properties

Camera

public PerspectiveCamera Camera

Gets or sets the perspective camera the carousel is viewed through, to change the viewpoint, the distance or the field of view.

Value
The default is null, which uses the carousel's own camera: at (0, 1, 6), looking towards the centre of the carousel with a 60-degree field of view.
Remarks

Move the camera nearer (a smaller Z) to make the carousel larger, raise it (a larger Y) to look down on the ring, or narrow the PerspectiveCamera.FieldOfView to flatten the perspective. CarouselViewport3DCamera, if set, takes precedence when the template is applied.

Example
<car:Carousel.Camera>
    <PerspectiveCamera Position="0,2,5" LookDirection="0,-2,-5" UpDirection="0,1,0" FieldOfView="50" />
</car:Carousel.Camera>
See also

CarouselViewport3DAmbientLightColor

public Color CarouselViewport3DAmbientLightColor

Gets or sets the colour of the light the carousel's items are lit by.

Value
The default is Colors.White: every item is shown in its own colours.
Remarks

The light is even and comes from everywhere, so it tints and darkens every item alike: a grey light dims the carousel, a warm one gives it a cast. It does not light the Control.Background.

CarouselViewport3DCamera

public Camera CarouselViewport3DCamera

Gets or sets the camera the carousel is viewed through, of any kind – for example an OrthographicCamera for a flat view without perspective.

Value
The default is null: the carousel uses Camera, or its own camera when that is null as well.
Remarks

When both this and Camera are set, this one is used when the template is applied; after that, the one set most recently is in effect. Setting either back to null leaves the camera in use unchanged.

See also

DistanceFromCentreToUser

public double DistanceFromCentreToUser

Gets or sets how far the item at the front is brought forward, towards the viewer.

Value
A distance in model units, where an item is one unit tall, added to the circle's radius. The default is 1.
Remarks

A larger value makes the front item appear larger, as it comes closer to the camera; too large and it passes the camera and disappears. To make the whole carousel larger or smaller, move the Camera instead.

See also

GapBetweenCurrentDisplayFrontItemAndOthers

public double GapBetweenCurrentDisplayFrontItemAndOthers

Gets or sets how far the items that are not at the front are pushed back, away from the viewer.

Value
A distance in model units, where an item is one unit tall. The default is 0.65.
Remarks

A larger gap sets the front item further apart from the rest, so it stands out more; 0 leaves every item on the circle itself.

See also

GapBetweenItems

public double GapBetweenItems

Gets or sets how far apart the items stand round the circle, which also sets the circle's size.

Value
The distance from one item to the next round the circle, in model units, where an item is one unit tall. The default is 0.25.
Remarks

The circle's circumference is this distance times the number of items, so the ring grows as items are added. Small values overlap the items behind the front one like a fanned deck; values around the width of an item spread them out side by side.

See also

IsReflectionRenderingEnabled

public bool IsReflectionRenderingEnabled

Gets or sets whether each item is drawn with a mirror-image reflection beneath it, fading to transparent, as though standing on a glossy floor.

Value
true to draw reflections. The default is false.
Remarks

The carousel draws the reflection itself, so it works for any item and any item template. Reflections suit a dark Control.Background.

Changing the property rebuilds every item. If the carousel has no ItemsControl.ItemTemplate of its own, or has the template keyed CarouselControlResources.CarouselItemReflectionEnabledTemplateKey, it is given the template keyed CarouselControlResources.CarouselItemTemplateKey at the same time; a template of your own is left alone.

ItemDimension

public Size ItemDimension

Gets or sets the size each item is drawn at before it is placed in 3D, which decides its shape and its sharpness.

Value
A size in logical pixels (1/96 inch). The default is 300 by 250. A size with a width or height of zero or less is read as the default.
Remarks

Each item is laid out at this size, as though in a window of its own, and the picture is then put on a panel one unit tall in 3D. So the ratio of width to height is the shape of every panel, and the size itself is the resolution: larger sizes stay sharp when the item is close to the camera. How large an item appears on screen is set by the camera and the carousel's own size, not by this.

Changing it rebuilds every item.

Example
<!-- Portrait book covers. -->
<car:Carousel ItemDimension="200,300" />

ItemRenderAngle

public double ItemRenderAngle

Gets or sets how far the items that are not at the front are turned away from the viewer.

Value
An angle in degrees, turning each item about its vertical axis. The default is 45.
Remarks

The front item always faces the viewer squarely. 0 leaves every item facing forwards, so the ring looks flat; values towards 90 show the others edge-on, so they almost disappear. The carousel turns to the new angle at once.

See also

SelectedIndex

public int SelectedIndex

Gets or sets the position of the item at the front of the carousel, facing the viewer.

Value
The zero-based position of the item in ItemsControl.Items. The default is -1: no item is at the front, and the items are not yet arranged round the circle.
Remarks

Setting it turns the carousel to bring that item forward, over half a second, and raises SelectedIndexChanged. It binds two-way by default, so a view model sees the user's choice. A value set before the control is loaded is applied once it is; a value outside the items is ignored and the carousel does not move.

When items are removed and the index falls past the last item, it moves to the last item.

Example
// Show the last product added.
gallery.SelectedIndex = gallery.Items.Count - 1;
See also

VisualChildrenCount

protected override int VisualChildrenCount

Gets the number of visual children: one once the template has been applied, otherwise none.

Methods

ClearContainerForItemOverride

protected override void ClearContainerForItemOverride(DependencyObject element, object item)

Takes an item off the carousel when it is removed, and brings the selection back within the remaining items.

Parameters
element
The container that held the item.
item
The item being removed.
Remarks

Call the base method when overriding, so the item's 3D panel is removed with it.

OnApplyTemplate

public override void OnApplyTemplate()

Finds the 3D viewport, the item container and the light in the template, and applies the camera and the light colour to them.

Remarks

A custom template provides a Viewport3D named PART_CarouselViewPort, a ContainerUIElement3D inside it named PART_CarouselItemContainer, an AmbientLight named viewport3DAmbientLight, and a hidden panel with IsItemsHost="True" for the item containers. Any of them may be left out; the features that need it then do nothing.

The camera applied is CarouselViewport3DCamera if set, otherwise Camera, otherwise the carousel's own.

OnMouseWheel

protected override void OnMouseWheel(MouseWheelEventArgs e)

Turns the carousel one item for each notch of the mouse wheel, and gives it keyboard focus.

Parameters
e
The wheel movement. Turning the wheel away from the user moves to the next item; towards the user, to the previous one.
Remarks

The event is marked handled only when the carousel actually moved, so at either end of the carousel the wheel goes on to scroll whatever contains it.

PrepareContainerForItemOverride

protected override void PrepareContainerForItemOverride(DependencyObject element, object item)

Sizes an item's container to ItemDimension and puts the item on the carousel.

Parameters
element
The container for the item, or the item itself when it is an element.
item
The item.
Remarks

Call the base method first when overriding, or the item does not appear.

Events

SelectedIndexChanged

public event EventHandler SelectedIndexChanged

Occurs when SelectedIndex changes, whether the user turned the carousel or code set the index.

Remarks

Raised as the carousel starts turning, with the new index already in SelectedIndex. Not raised for changes made before the control is loaded. A value set outside the items still raises it, although the carousel does not move.

Example
gallery.SelectedIndexChanged += (sender, e) =>
{
    Product product = (Product)gallery.Items[gallery.SelectedIndex];
    priceText.Text = product.Price.ToString("C");
};

Fields

CameraProperty static

public static readonly DependencyProperty CameraProperty

Identifies the Camera dependency property.

CarouselViewport3DAmbientLightColorProperty static

public static readonly DependencyProperty CarouselViewport3DAmbientLightColorProperty

Identifies the CarouselViewport3DAmbientLightColor dependency property.

CarouselViewport3DCameraProperty static

public static readonly DependencyProperty CarouselViewport3DCameraProperty

Identifies the CarouselViewport3DCamera dependency property.

DistanceFromCentreToUserProperty static

public static readonly DependencyProperty DistanceFromCentreToUserProperty

Identifies the DistanceFromCentreToUser dependency property.

GapBetweenCurrentDisplayFrontItemAndOthersProperty static

public static readonly DependencyProperty GapBetweenCurrentDisplayFrontItemAndOthersProperty

Identifies the GapBetweenCurrentDisplayFrontItemAndOthers dependency property.

GapBetweenItemsProperty static

public static readonly DependencyProperty GapBetweenItemsProperty

Identifies the GapBetweenItems dependency property.

IsReflectionRenderingEnabledProperty static

public static readonly DependencyProperty IsReflectionRenderingEnabledProperty

Identifies the IsReflectionRenderingEnabled dependency property.

ItemDimensionProperty static

public static readonly DependencyProperty ItemDimensionProperty

Identifies the ItemDimension dependency property.

ItemRenderAngleProperty static

public static readonly DependencyProperty ItemRenderAngleProperty

Identifies the ItemRenderAngle dependency property.

MoveToLeft static

public static RoutedCommand MoveToLeft

The command that moves the selection to the previous item; bound to the Left arrow key.

Remarks

Disabled while the first item (or no item) is selected, so a button using it greys out at the start of the carousel. Give a button the command and the carousel as its CommandTarget, or let it find the carousel through keyboard focus.

The Left arrow key works whenever the carousel has keyboard focus, which it takes when the user clicks it or turns the mouse wheel over it.

Example
<Button Content="Previous" Command="{x:Static car:Carousel.MoveToLeft}" CommandTarget="{Binding ElementName=Gallery}" />
See also

MoveToRight static

public static RoutedCommand MoveToRight

The command that moves the selection to the next item; bound to the Right arrow key.

Remarks

Disabled while the last item is selected, so a button using it greys out at the end of the carousel. See MoveToLeft for how to use it.

See also

SelectedIndexProperty static

public static readonly DependencyProperty SelectedIndexProperty

Identifies the SelectedIndex dependency property.