Click here to Skip to main content
15,886,065 members
Articles / Desktop Programming / WPF

WPF 2D Image Carousel

Rate me:
Please Sign up or sign in to vote.
4.95/5 (31 votes)
18 Mar 2011CPOL3 min read 122.4K   8.7K   81  
A 2D carousel like UserControl in WPF
Imports System.Windows.Threading

Class ImageCarousel

    Private InitMouseX As Double
    Private InitMouseY As Double
    Private FinalMouseX As Double
    Private FinalMouseY As Double

    Private DiffX As Double
    Private DiffY As Double

    Private move As Integer
    Private shift As Double = 15
    Private scale As Double = 1.2

    Private MidCanvasX As Double
    Private ImgGridHeight As Double = 95
    Private ImgGridWidth As Double = 135

    Private IsCarouseling As Boolean

    Private CarouselTimer As New DispatcherTimer

    Private GridScaleTr_1 As New ScaleTransform
    Private GridScaleTr_2 As New ScaleTransform
    Private GridScaleTr_3 As New ScaleTransform
    Private GridScaleTr_4 As New ScaleTransform
    Private GridScaleTr_5 As New ScaleTransform

    Private Sub ImageCarousel_Initialized(ByVal sender As Object, _
                                        ByVal e As System.EventArgs) Handles Me.Initialized

        AddHandler CarouselTimer.Tick, AddressOf CarouselTimer_Tick
        CarouselTimer.Interval = New TimeSpan(0, 0, 0, 0, 100)

        ImageGrid_1.RenderTransform = GridScaleTr_1
        ImageGrid_2.RenderTransform = GridScaleTr_2
        ImageGrid_3.RenderTransform = GridScaleTr_3
        ImageGrid_4.RenderTransform = GridScaleTr_4
        ImageGrid_5.RenderTransform = GridScaleTr_5

        ' Increase the scale of the Grid in the middle
        ' of the UserControl.
        Dim y As Double = Canvas.GetTop(ImageGrid_3)
        MidCanvasX = CarouselCanvas.ActualWidth / 2
        GridScaleTr_3.ScaleX = scale
        GridScaleTr_3.ScaleY = scale
        GridScaleTr_3.CenterX = MidCanvasX + (ImgGridWidth / 2)
        GridScaleTr_3.CenterY = y + (ImgGridHeight / 2)

        ChangeImagesOpacity()
    End Sub

    Private Sub CarouselCanvas_MouseLeftButtonDown(ByVal sender As Object, _
                                                   ByVal e As System.Windows.Input.MouseButtonEventArgs) _
                                                   Handles CarouselCanvas.MouseLeftButtonDown
        If IsCarouseling = False Then
            InitMouseX = e.GetPosition(CarouselCanvas).X
            InitMouseY = e.GetPosition(CarouselCanvas).Y
        End If
    End Sub

    Private Sub CarouselCanvas_MouseLeftButtonUp(ByVal sender As Object, _
                                                 ByVal e As System.Windows.Input.MouseButtonEventArgs) _
                                                 Handles CarouselCanvas.MouseLeftButtonUp
        If IsCarouseling = False Then
            IsCarouseling = True

            FinalMouseX = e.GetPosition(CarouselCanvas).X
            FinalMouseY = e.GetPosition(CarouselCanvas).Y

            DiffX = FinalMouseX - InitMouseX
            DiffY = FinalMouseY - InitMouseY

            ' Check whether swipe is horizontal.
            If Math.Abs(DiffX) > Math.Abs(DiffY) Then
                CarouselTimer.Start()
            Else
                IsCarouseling = False
            End If
        End If
    End Sub

    Private Sub CarouselTimer_Tick(ByVal sender As Object, ByVal e As EventArgs)
        If move <> 135 Then
            MoveImageGrids()
            move += shift
            ChangeImagesOpacity()
        Else
            CarouselTimer.Stop()
            move = 0
            IsCarouseling = False
        End If
    End Sub

    Private Sub MoveImageGrids()
        ' Right swipe.
        If DiffX > 0 Then
            For Each ImgGrid As Grid In CarouselCanvas.Children
                Dim x As Double = Canvas.GetLeft(ImgGrid)
                Canvas.SetLeft(ImgGrid, (x + shift))
                RightCheckOriginals(ImgGrid)
                RghtCheckCopy1s(ImgGrid)
                RghtCheckCopy2s(ImgGrid)
                ScaleUpGrid(ImgGrid)
                ScaleGridToNormal(ImgGrid)
            Next
        Else
            ' Left swipe.
            For Each ImgGrid As Grid In CarouselCanvas.Children
                Dim x As Double = Canvas.GetLeft(ImgGrid)
                Canvas.SetLeft(ImgGrid, (x - shift))
                LeftCheckOriginals(ImgGrid)
                LeftCheckCopy1s(ImgGrid)
                LeftCheckCopy2s(ImgGrid)
                ScaleUpGrid(ImgGrid)
                ScaleGridToNormal(ImgGrid)
            Next
        End If
    End Sub

    ' Set the location of main ImageGrids's to zero
    ' when their x-position reaches right-edge of canvas.
    Private Sub RightCheckOriginals(ByVal ImgGrid As Grid)
        If (ImgGrid Is ImageGrid_1) Or (ImgGrid Is ImageGrid_2) _
        Or (ImgGrid Is ImageGrid_3) Or (ImgGrid Is ImageGrid_4) _
        Or (ImgGrid Is ImageGrid_5) Then
            If Canvas.GetLeft(ImgGrid) >= 675 Then
                Canvas.SetLeft(ImgGrid, 0)
            End If
        End If
    End Sub

    ' Set the location of ImageGrid's on right side
    ' of the main ImageGrids to -675 when their x-position
    ' reaches zero.
    Private Sub RghtCheckCopy1s(ByVal ImgGrid As Grid)
        If (ImgGrid Is ImageGrid_1_Copy1) Or (ImgGrid Is ImageGrid_2_Copy1) _
        Or (ImgGrid Is ImageGrid_3_Copy1) Or (ImgGrid Is ImageGrid_4_Copy1) _
        Or (ImgGrid Is ImageGrid_5_Copy1) Then
            If Canvas.GetLeft(ImgGrid) >= 0 Then
                Canvas.SetLeft(ImgGrid, -675)
            End If
        End If
    End Sub

    ' Place the ImageGrids on the right of the main
    ' grids to the appropriate location when one of
    ' those Grids exceeds a certain limit.
    Private Sub RghtCheckCopy2s(ByVal ImgGrid As Grid)
        If (ImgGrid Is ImageGrid_1_Copy2) Or (ImgGrid Is ImageGrid_2_Copy2) _
        Or (ImgGrid Is ImageGrid_3_Copy2) Or (ImgGrid Is ImageGrid_4_Copy2) _
        Or (ImgGrid Is ImageGrid_5_Copy2) Then
            If Canvas.GetLeft(ImgGrid) >= 1350 Then
                Canvas.SetLeft(ImgGrid, 675)
            End If
        End If
    End Sub

    Private Sub LeftCheckOriginals(ByVal ImgGrid As Grid)
        If (ImgGrid Is ImageGrid_1) Or (ImgGrid Is ImageGrid_2) _
        Or (ImgGrid Is ImageGrid_3) Or (ImgGrid Is ImageGrid_4) _
        Or (ImgGrid Is ImageGrid_5) Then
            If Canvas.GetLeft(ImgGrid) <= -135 Then
                Canvas.SetLeft(ImgGrid, (675 + Canvas.GetLeft(ImgGrid)))
            End If
        End If
    End Sub

    Private Sub LeftCheckCopy1s(ByVal ImgGrid As Grid)
        If (ImgGrid Is ImageGrid_1_Copy1) Or (ImgGrid Is ImageGrid_2_Copy1) _
        Or (ImgGrid Is ImageGrid_3_Copy1) Or (ImgGrid Is ImageGrid_4_Copy1) _
        Or (ImgGrid Is ImageGrid_5_Copy1) Then
            If Canvas.GetLeft(ImgGrid) <= -810 Then
                Canvas.SetLeft(ImgGrid, -135)
            End If
        End If
    End Sub

    Private Sub LeftCheckCopy2s(ByVal ImgGrid As Grid)
        If (ImgGrid Is ImageGrid_1_Copy2) Or (ImgGrid Is ImageGrid_2_Copy2) _
        Or (ImgGrid Is ImageGrid_3_Copy2) Or (ImgGrid Is ImageGrid_4_Copy2) _
        Or (ImgGrid Is ImageGrid_5_Copy2) Then
            If Canvas.GetLeft(ImgGrid) <= 540 Then
                Canvas.SetLeft(ImgGrid, (1350 - 135))
            End If
        End If
    End Sub

    ' Increase the scale of the Grid in the middle.
    Private Sub ScaleUpGrid(ByVal ImgGrid As Grid)
        Dim x As Double = Canvas.GetLeft(ImgGrid)
        Dim y As Double = Canvas.GetTop(ImgGrid)
        If (ImgGrid Is ImageGrid_1) And x = 270 Then
            GridScaleTr_1.ScaleX = scale
            GridScaleTr_1.ScaleY = scale
            GridScaleTr_1.CenterX = MidCanvasX + (ImgGridWidth / 2)
            GridScaleTr_1.CenterY = y + (ImgGridHeight / 2)
        ElseIf (ImgGrid Is ImageGrid_2) And x = 270 Then
            GridScaleTr_2.ScaleX = scale
            GridScaleTr_2.ScaleY = scale
            GridScaleTr_2.CenterX = MidCanvasX + (ImgGridWidth / 2)
            GridScaleTr_2.CenterY = y + (ImgGridHeight / 2)
        ElseIf (ImgGrid Is ImageGrid_3) And x = 270 Then
            GridScaleTr_3.ScaleX = scale
            GridScaleTr_3.ScaleY = scale
            GridScaleTr_3.CenterX = MidCanvasX + (ImgGridWidth / 2)
            GridScaleTr_3.CenterY = y + (ImgGridHeight / 2)
        ElseIf (ImgGrid Is ImageGrid_4) And x = 270 Then
            GridScaleTr_4.ScaleX = scale
            GridScaleTr_4.ScaleY = scale
            GridScaleTr_4.CenterX = MidCanvasX + (ImgGridWidth / 2)
            GridScaleTr_4.CenterY = y + (ImgGridHeight / 2)
        ElseIf (ImgGrid Is ImageGrid_5) And x = 270 Then
            GridScaleTr_5.ScaleX = scale
            GridScaleTr_5.ScaleY = scale
            GridScaleTr_5.CenterX = MidCanvasX + (ImgGridWidth / 2)
            GridScaleTr_5.CenterY = y + (ImgGridHeight / 2)
        End If
    End Sub

    ' Scale Grids that are not in the middle to their
    ' normal scale.
    Private Sub ScaleGridToNormal(ByVal ImgGrid As Grid)
        Dim x As Double = Canvas.GetLeft(ImgGrid)
        Dim y As Double = Canvas.GetTop(ImgGrid)
        If (ImgGrid Is ImageGrid_1) And x <> 270 Then
            GridScaleTr_1.ScaleX = 1
            GridScaleTr_1.ScaleY = 1
        ElseIf (ImgGrid Is ImageGrid_2) And x <> 270 Then
            GridScaleTr_2.ScaleX = 1
            GridScaleTr_2.ScaleY = 1
        ElseIf (ImgGrid Is ImageGrid_3) And x <> 270 Then
            GridScaleTr_3.ScaleX = 1
            GridScaleTr_3.ScaleY = 1
        ElseIf (ImgGrid Is ImageGrid_4) And x <> 270 Then
            GridScaleTr_4.ScaleX = 1
            GridScaleTr_4.ScaleY = 1
        ElseIf (ImgGrid Is ImageGrid_5) And x <> 270 Then
            GridScaleTr_5.ScaleX = 1
            GridScaleTr_5.ScaleY = 1
        End If
    End Sub

    Private Sub ChangeImagesOpacity()
        For Each ImgGrid As Grid In CarouselCanvas.Children
            If Canvas.GetLeft(ImgGrid) <> 270 Then
                For Each el As UIElement In ImgGrid.Children
                    If TypeOf (el) Is Image Then
                        el.Opacity = 0.6
                    End If
                Next
            ElseIf Canvas.GetLeft(ImgGrid) = 270 Then
                For Each el As UIElement In ImgGrid.Children
                    If TypeOf (el) Is Image Then
                        el.Opacity = 1
                    End If
                Next
            End If
        Next
    End Sub

#Region "Dependency properties"
    ' Image_1s dependency property.
    Public Property Image1Source() As ImageSource
        Get
            Return CType(GetValue(Image1Property), ImageSource)
        End Get
        Set(ByVal value As ImageSource)
            SetValue(Image1Property, value)
        End Set
    End Property

    Public Shared Image1Property As DependencyProperty = _
        DependencyProperty.Register("Image1Source", _
                                    GetType(ImageSource), _
                                    GetType(ImageCarousel), _
                                    New FrameworkPropertyMetadata( _
                                    New PropertyChangedCallback(AddressOf ChangeSource1)))

    Private Shared Sub ChangeSource1(ByVal source As DependencyObject, _
                                     ByVal e As DependencyPropertyChangedEventArgs)
        CType(source, ImageCarousel).Image_1.Source = CType(e.NewValue, ImageSource)
        CType(source, ImageCarousel).Image_1_Copy1.Source = CType(e.NewValue, ImageSource)
        CType(source, ImageCarousel).Image_1_Copy2.Source = CType(e.NewValue, ImageSource)
    End Sub

    ' Image_2s dependency property.
    Public Property Image2Source() As ImageSource
        Get
            Return CType(GetValue(Image2Property), ImageSource)
        End Get
        Set(ByVal value As ImageSource)
            SetValue(Image2Property, value)
        End Set
    End Property

    Public Shared Image2Property As DependencyProperty = _
        DependencyProperty.Register("Image2Source", _
                                    GetType(ImageSource), _
                                    GetType(ImageCarousel), _
                                    New FrameworkPropertyMetadata( _
                                    New PropertyChangedCallback(AddressOf ChangeSource2)))

    Private Shared Sub ChangeSource2(ByVal source As DependencyObject, _
                                     ByVal e As DependencyPropertyChangedEventArgs)
        CType(source, ImageCarousel).Image_2.Source = CType(e.NewValue, ImageSource)
        CType(source, ImageCarousel).Image_2_Copy1.Source = CType(e.NewValue, ImageSource)
        CType(source, ImageCarousel).Image_2_Copy2.Source = CType(e.NewValue, ImageSource)
    End Sub

    ' Image_3s dependency property.
    Public Property Image3Source() As ImageSource
        Get
            Return CType(GetValue(Image3Property), ImageSource)
        End Get
        Set(ByVal value As ImageSource)
            SetValue(Image3Property, value)
        End Set
    End Property

    Public Shared Image3Property As DependencyProperty = _
        DependencyProperty.Register("Image3Source", _
                                    GetType(ImageSource), _
                                    GetType(ImageCarousel), _
                                    New FrameworkPropertyMetadata( _
                                    New PropertyChangedCallback(AddressOf ChangeSource3)))

    Private Shared Sub ChangeSource3(ByVal source As DependencyObject, _
                                     ByVal e As DependencyPropertyChangedEventArgs)
        CType(source, ImageCarousel).Image_3.Source = CType(e.NewValue, ImageSource)
        CType(source, ImageCarousel).Image_3_Copy1.Source = CType(e.NewValue, ImageSource)
        CType(source, ImageCarousel).Image_3_Copy2.Source = CType(e.NewValue, ImageSource)
    End Sub

    ' Image_4s dependency property.
    Public Property Image4Source() As ImageSource
        Get
            Return CType(GetValue(Image4Property), ImageSource)
        End Get
        Set(ByVal value As ImageSource)
            SetValue(Image4Property, value)
        End Set
    End Property

    Public Shared Image4Property As DependencyProperty = _
        DependencyProperty.Register("Image4Source", _
                                    GetType(ImageSource), _
                                    GetType(ImageCarousel), _
                                    New FrameworkPropertyMetadata( _
                                    New PropertyChangedCallback(AddressOf ChangeSource4)))

    Private Shared Sub ChangeSource4(ByVal source As DependencyObject, _
                                     ByVal e As DependencyPropertyChangedEventArgs)
        CType(source, ImageCarousel).Image_4.Source = CType(e.NewValue, ImageSource)
        CType(source, ImageCarousel).Image_4_Copy1.Source = CType(e.NewValue, ImageSource)
        CType(source, ImageCarousel).Image_4_Copy2.Source = CType(e.NewValue, ImageSource)
    End Sub

    ' Image_5s dependency property.
    Public Property Image5Source() As ImageSource
        Get
            Return CType(GetValue(Image1Property), ImageSource)
        End Get
        Set(ByVal value As ImageSource)
            SetValue(Image5Property, value)
        End Set
    End Property

    Public Shared Image5Property As DependencyProperty = _
        DependencyProperty.Register("Image5Source", _
                                    GetType(ImageSource), _
                                    GetType(ImageCarousel), _
                                    New FrameworkPropertyMetadata( _
                                    New PropertyChangedCallback(AddressOf ChangeSource5)))

    Private Shared Sub ChangeSource5(ByVal source As DependencyObject, _
                                     ByVal e As DependencyPropertyChangedEventArgs)
        CType(source, ImageCarousel).Image_5.Source = CType(e.NewValue, ImageSource)
        CType(source, ImageCarousel).Image_5_Copy1.Source = CType(e.NewValue, ImageSource)
        CType(source, ImageCarousel).Image_5_Copy2.Source = CType(e.NewValue, ImageSource)
    End Sub
#End Region
End Class

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

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


Written By
Software Developer
Kenya Kenya
Experienced C# software developer with a passion for WPF.

Awards,
  • CodeProject MVP 2013
  • CodeProject MVP 2012
  • CodeProject MVP 2021

Comments and Discussions