WPF carousels / rotating elements

I am developing software that takes automatic photos with a camera. I want the user to be able to set the photo interval. I would like it to look and work like a carousel.

This is how it should look:

when i scroll (or drag with mouse) it should move in the given direction:

the selected element must always be in the middle and, if it is the last, the first one must rotate to the right (or vice versa).

I've already added the basic swipe / drag functionality, it recognizes whenever an action has been taken and in which direction. Hovewer, I have no idea how to actually move items.

Items are currently defined as follows:

<StackPanel x:Name="countdownContainer" Background="{StaticResource GuiSideBarBackgroundColor}" Orientation="Horizontal" HorizontalAlignment="Center">
    <TextBlock Style="{StaticResource CountdownElement}" Text="3s"/>
    <TextBlock Style="{StaticResource CountdownElementSelected}" Text="5s"/>
    <TextBlock Style="{StaticResource CountdownElement}" Text="10s"/>


I know some animation basics, but I don't know how to animate them like I need to here. Wouldn't it be better to use some other controls instead of StackPanel and TextBlock?


source to share

1 answer

I am relying on the styles you listed above but not included in the code. You can do it in pure xaml and viewmodel. This will be a very basic and crude example. Alternatively, you can implement your own control that inherits from a class that has a Selector somewhere down the hierarchy, rather than the default one provided by the default cust control pattern, and I recommend that you take a look at the MVVM pattern and Galasoft MVVM Light. In this example I have excluded touch gestures , they are easy to implement and use EventToCommand, you can use them directly in your vm or custcontrol *.


<ItemsPanelTemplate x:Key="YourItemsPanelTemplate">
   <VirtualizingStackPanel Orientation="Horizontal"/>

<DataTemplate x:Key="YourDataTemplate">
    <TextBlock Style="{StaticResource CountdownElement}" Text="{Binding .}" x:Name="PART_TextBlock"/>
        Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType= {x:Type ListViewItem}},Path=IsSelected}" Value="True"> 
            <!-- Here I'm just changing your fontsize, do whatever you want here :) -->                                       
            <Setter Property="FontSize" Value="34" TargetName="PART_TextBlock"/>

<Style x:Key="YourContainerStyle" TargetType="ListViewItem">
    <Setter Property="HorizontalContentAlignment" Value="Center" />
    <Setter Property="VerticalContentAlignment" Value="Bottom" />
    <Setter Property="Background" Value="Transparent" />
    <Setter Property="BorderThickness" Value="0" />
    <Setter Property="Margin" Value="10,0,10,0" />
    <Setter Property="Padding" Value="0" />
    <Setter Property="Template">
            <ControlTemplate TargetType="{x:Type ListViewItem}">
                <ContentPresenter x:Name="PART_ContentPresenter"
                                HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                                Margin="{TemplateBinding Padding}"
                                Content="{TemplateBinding Content}"
                                ContentTemplate="{StaticResource YourDataTemplate}" />

<Style x:Key="YourListBoxStyle" TargetType="ListBox">
    <Setter Property="ItemContainerStyle" Value="{StaticResource YourContainerStyle}"/>
    <Setter Property="ItemTemplate" Value="{StaticResource YourDataTemplate}"/>
    <Setter Property="ItemsPanel" Value="{StaticResource YourItemsPanelTemplate}"/>


Here are your styles, now for the xaml code, notice that I am binding your objects here and using the styles described above.


    <ListView Background="{StaticResource  GuiSideBarBackgroundColor}" 
        Style="{StaticResource YourListBoxStyle}"
        ItemsSource="{Binding CountDownElements}"
        SelectedItem="{Binding SelectedItem, Mode=TwoWay}"/>


ViewModel Remember to set this as the datacontext for your view or copy the code into your code.

public class YourViewModel : INotifyPropertyChanged
    private ObservableCollection<string> countDownElements = new ObservableCollection<string> { "1s", "2s", "3s", "4s", "5s", "6s", "7s", "8s", "9s", "10s" };
    private string selectedItem;

    public ObservableCollection<string> CountDownElements
        get { return countDownElements; }
            if (Equals(value, countDownElements)) return;
            countDownElements = value;

    public string SelectedItem
        get { return selectedItem; }
            if (value == selectedItem) return;
            selectedItem = value;

    public event PropertyChangedEventHandler PropertyChanged;

    [NotifyPropertyChangedInvocator] // remove if you don't have R#
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));



Very simple stuff

Hope this helps, or at least kicks you in the right direction! :)





All Articles