Click here to Skip to main content
15,867,453 members
Articles / Desktop Programming / WPF

A Custom WPF Carousel Control

Rate me:
Please Sign up or sign in to vote.
5.00/5 (30 votes)
21 Nov 2019CPOL4 min read 56.6K   3.2K   49   29
This article presents a simple WPF Carousel Control

Introduction

A carousel control is a powerful and visually appealing way to present multiple items of data. Unfortunately, Microsoft does not provide a stock implementation. There are many freely available carousel controls available.

The two best known freeware carousel controls are arguably the following:

Initially, I tried using the first version, and adapting it to our own needs. Unfortunately, it is based on the Microsoft PathListBox control thereby hiding most of the implementation details. I found it rather difficult to modify it to suit our needs and eventually gave up.

The second carousel is a nice simple implementation, but the author has hard coded spheres as the carousel items, and he has not exposed any dependency properties which limits its usefulness.

I decided to use the second carousel as a starting point to create a more flexible carousel control.

This article includes the source code for the new WPF carousel control, and a simple demonstration application.

Background

You will need a good understanding of C# and a basic understanding of WPF.

Overview

The carousel control can arrange items horizontally:

It can also arrange the items vertically:

The new carousel control, which I have called WPFCarouselControl (no marks for originality, I fear) has the following dependency properties:

ItemsSource

The data displayed by the carousel items.
SelectedItem The currently selected item.
CarouselItemTemplate Defines the appearance and behaviour of each carousel item.
AutoSizeToParent If true, the control sizes itself to fit the available space.
TiltInDegrees The tilt of the axis about which the items appear to rotate.
RotationSpeed The speed at which the items rotate when a new item is selected.
Fade A value between 0 and 1 which determines how the opacity of items varies with position. Those furthest from the selected item have the lowest opacity.
Scale A scaling that is applied to the items in the carousel to create a 3D effect. A value of one means that all items have the same size. A value less than one creates perspective. The range is 0 to 1 inclusive.
VerticalOrientation If true items are arranged vertically, if false items are arranged horizontally.

Using the WPFCarouselControl

It is straightforward to use the control in an application.

First, create a class which stores the data displayed in one carousel item. For example:

C#
public class RadioStation
{
    public string Name { get; set; }
    public string ShortName { get; set; }
    public string ImageSource { get; set; }
    public string Text { get; set; }
}

Next, add a CarouselControl to your view. For example:

XAML
<WPFCarouselControl:CarouselControl Grid.Row="5" Grid.Column="1" 
Grid.ColumnSpan="5" x:Name="_carouselDABRadioStations" 
ItemsSource="{Binding RadioStationsDAB}" 
SelectedItem="{Binding SelectedRadioStationDAB,Mode=TwoWay}" 
ShowRotation="True"  TiltInDegrees="10" 
AutoSizeToParent="true" RotationSpeed="100" 
VerticalOrientation="False" HorizontalAlignment="Stretch" 
VerticalAlignment="Stretch">
    <WPFCarouselControl:CarouselControl.Style>
        <Style TargetType="WPFCarouselControl:CarouselControl">
            <Setter Property="CarouselItemTemplate" >
                <Setter.Value>
                    <ControlTemplate>
                        <Border BorderThickness="1" 
                        BorderBrush="Gainsboro" Background="SteelBlue" 
                        Width="250" Height="150">
                            <Grid>
                                <Grid.RowDefinitions>
                                    <RowDefinition Height="*"/>
                                    <RowDefinition Height="30"/>
                                </Grid.RowDefinitions>
                                <Border Grid.Row="0" 
                                BorderThickness="0" Background="White">
                                    <Image Grid.Row="0" 
                                    Source="{Binding ImageSource}" 
                                    VerticalAlignment="Center" 
                                    HorizontalAlignment="Center" Height="100"/>
                                </Border>
                                <Label Grid.Row="1" 
                                Content="{Binding ShortName}" 
                                Foreground="White" Background="Transparent" 
                                FontSize="20" FontFamily="Arial" 
                                Style="{StaticResource labelStyleCentred}" 
                                DockPanel.Dock="Bottom" Height="Auto"/>
                            </Grid>
                        </Border>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </WPFCarouselControl:CarouselControl.Style>
</WPFCarouselControl:CarouselControl>

Note the CarouselItemTemplate property which defines a carousel item consisting of a rectangle containing an image above a line of text.

The ItemsSource property is bound to the RadioStationsDAB property defined in the view model as follows:

C#
private System.Collections.ObjectModel.ObservableCollection
                              <Model.RadioStation> _radioStationsDAB;
public System.Collections.ObjectModel.ObservableCollection
                              <Model.RadioStation> RadioStationsDAB
{
    get
    {
        return _radioStationsDAB;
    }
    set
    {
        _radioStationsDAB = value;
        NotifyPropertyChanged("RadioStationsDAB");
    }
}

Implementation Details

The WPF carousel control is a WPF user control containing a Canvas control.

The item controls are child elements of the canvas, laid out on a circle projected onto the plane of the screen.

The control implements a SelectionChanged event allowing the owner to receive a notification when an item is selected by means of a left mouse button click.

The rotation is implemented using a timer which is started when the selected item changes. The timer fires every 10 milliseconds to ensure a smooth rotation. On each tick, it moves the items by an amount proportional to the rotation speed.

Adding/Removing Items

The ItemsSource property assumes that it is bound to a collection object that implements the System.Collections.IEnumerable and System.Collections.Specialized.INotifyCollectionChanged interfaces. The latter interface must be implemented if items are added and/or removed from the items list. 

Limitations

The current control lays out the items uniformly around an imaginary circle. If you wish to change the layout, you will need to edit the SetElementPositions method. If you are feeling adventurous, you could layout the items along a Path dependency property.

History

  • 9th May, 2019: Version 1
  • 9th May, 2019: Version 2: Implemented the CarouselItemTemplate dependency property
  • 5th November, 2019: Version 3: Fixed a bug with the rotation algorithm that caused the direction of rotation to reverse unexpectedly. The download code has been updated.
  • 21st November, 2019: Version 4: Updated the ItemsSource property to allow the adding and/or removing of items.  
  • 22nd November, 2019: Version 5: Fixed the layout so that the selected item is now always centred. 

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
United Kingdom United Kingdom
C#/WPF/C++ Windows developer

Comments and Discussions

 
SuggestionUpdate to .Net 6 Pin
Daniele Alberto Galliano20-Mar-22 11:37
professionalDaniele Alberto Galliano20-Mar-22 11:37 
Question.Your code is very helpul, powerful and interesting.But it is difficult for me to understand how it works. Pin
Trẻ Người lính10-Dec-21 10:20
Trẻ Người lính10-Dec-21 10:20 
Questioncenter align items of different widths when vertical orientation is true Pin
julesx41627-Apr-21 11:53
julesx41627-Apr-21 11:53 
QuestionSelectedItem template Pin
samuel almeida30-Oct-20 6:13
samuel almeida30-Oct-20 6:13 
Questionlinking items to separate forms,I wonder how I can do it Pin
Member 1460389927-Mar-20 3:42
Member 1460389927-Mar-20 3:42 
AnswerRe: linking items to separate forms,I wonder how I can do it Pin
Member 1460389927-Mar-20 3:52
Member 1460389927-Mar-20 3:52 
GeneralMy vote of 5 Pin
m palotas3-Dec-19 14:50
m palotas3-Dec-19 14:50 
GeneralRe: My vote of 5 Pin
Leif Simon Goodwin3-Dec-19 22:32
Leif Simon Goodwin3-Dec-19 22:32 
QuestionDelete Item's from Carousel Pin
leighdar18-Nov-19 0:43
leighdar18-Nov-19 0:43 
How can I delete a item,

I have remove an item from the Carousel, if I remove am item from the view model it doe not revove it from the carousel.

Thanks
AnswerRe: Delete Item's from Carousel Pin
Leif Simon Goodwin21-Nov-19 4:35
Leif Simon Goodwin21-Nov-19 4:35 
QuestionAwsome...One request Pin
faisalthayyil16-Nov-19 18:43
faisalthayyil16-Nov-19 18:43 
AnswerRe: Awsome...One request Pin
Jaroslav Mitrovic22-Nov-19 22:47
Jaroslav Mitrovic22-Nov-19 22:47 
QuestionNot all the items are centered correctly Pin
Member 1357019115-Nov-19 3:50
Member 1357019115-Nov-19 3:50 
AnswerRe: Not all the items are centered correctly Pin
Leif Simon Goodwin24-Nov-19 22:52
Leif Simon Goodwin24-Nov-19 22:52 
PraiseNice work Pin
Mike Hankey8-Nov-19 12:16
mveMike Hankey8-Nov-19 12:16 
Praisevery nice Pin
BillW337-Nov-19 3:20
professionalBillW337-Nov-19 3:20 
GeneralRe: very nice Pin
Leif Simon Goodwin7-Nov-19 5:26
Leif Simon Goodwin7-Nov-19 5:26 
GeneralMy vote of 5 Pin
Сергій Ярошко5-Nov-19 4:01
professionalСергій Ярошко5-Nov-19 4:01 
QuestionShowing only selected item Pin
Member 1459432011-Oct-19 2:40
Member 1459432011-Oct-19 2:40 
AnswerRe: Showing only selected item Pin
Member 145943204-Nov-19 22:19
Member 145943204-Nov-19 22:19 
AnswerRe: Showing only selected item Pin
Leif Simon Goodwin22-Nov-19 3:17
Leif Simon Goodwin22-Nov-19 3:17 
Questionfew things Pin
Sacha Barber10-May-19 4:23
Sacha Barber10-May-19 4:23 
AnswerRe: few things Pin
Leif Simon Goodwin10-May-19 4:29
Leif Simon Goodwin10-May-19 4:29 
GeneralRe: few things Pin
Sacha Barber10-May-19 4:42
Sacha Barber10-May-19 4:42 
GeneralRe: few things Pin
Leif Simon Goodwin5-Nov-19 1:14
Leif Simon Goodwin5-Nov-19 1:14 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.