Click here to Skip to main content
13,248,369 members (56,741 online)
Click here to Skip to main content
Add your own
alternative version


42 bookmarked
Posted 15 May 2012

WPF: Belt Clock

, 17 May 2012
Rate this:
Please Sign up or sign in to vote.
A WPF belt clock


This work is inspired by a pricey watch which I spotted while perusing one of those magazines filled with other shockingly pricey items. This is a more affordable offering and minus bulletproof glass.

Design and Layout

I designed the Belt Clock in Expression Blend. The belts are made up of Grids, containing TextBlocks, stacked in a layout container of type Canvas.

HourCanvas, plus some other elements that make up the visual components of the belt, are placed in another layout container whose ClipToBounds property is set to True.

Here's how it actually looks like when the ClipToBounds property of all the concerned layout containers are set to False.

The Code

The logic for ensuring that the correct time is 'displayed' is contained in a class called TickTock. When the application is loaded the method SetTimeOnLoad() calls several methods to ensure that the correct time is highlighted.

Public Sub SetTimeOnLoad()
    GetTime(currentHour, currentMinute_1, currentMinute_2)

    ' Highlight hour.     
    DisplayTimeOnLoad(hourCanvas, currentHour, hourStartGrid, _
                      hourGridUpperLimit, hourGridLowerLimit)

    ' Highlight first part of minutes.        
    DisplayTimeOnLoad(min1Canvas, currentMinute_1, min1StartGrid, _
                      min1GridUpperLimit, min1GridLowerLimit)

    ' Highlight second part of minutes.        
    DisplayTimeOnLoad(min2Canvas, currentMinute_2, min2StartGrid, _
                      min2GridUpperLimit, min2GridLowerLimit)
End Sub

The GetTime() method sets the value of several fields with the current time.

Private Sub GetTime(ByRef hour As Integer, ByRef min1 As Integer, ByRef min2 As Integer)
    hour = DateTime.Now.Hour

    If (hour > 12) Then
        hour -= 12
    End If

    If (DateTime.Now.Minute.ToString.Length = 1) Then
        min1 = 0
        min2 = CInt(DateTime.Now.Minute.ToString.Substring(0, 1))
        min1 = CInt(DateTime.Now.Minute.ToString.Substring(0, 1))
        min2 = CInt(DateTime.Now.Minute.ToString.Substring(1, 1))
    End If
End Sub

The DisplayTimeOnLoad() method ensures that the correct time is highlighted.

Private Sub DisplayTimeOnLoad(ByRef cnv As Canvas, ByVal currTime As Integer, _
                              ByVal startGrid As Integer, ByVal upperLimit As Integer, _
                              ByVal lowerLimit As Integer)
    If (currTime < startGrid) Then
        ' Move grids downwards.
        shift = (startGrid - currTime) * gridHeight

        While (shift > 0)
            For Each grd In cnv.Children
                initY = Canvas.GetTop(grd)
                newY = initY + 1
                Canvas.SetTop(grd, newY)
                PlaceGridInLimitPosition(grd, upperLimit, lowerLimit)

            shift -= 1
        End While
    ElseIf (currTime > startGrid) Then
        ' Move grids upwards.
        shift = (currTime - startGrid) * gridHeight

        While (shift > 0)
            For Each grd In cnv.Children
                initY = Canvas.GetTop(grd)
                newY = initY - 1
                Canvas.SetTop(grd, newY)
                PlaceGridInLimitPosition(grd, upperLimit, lowerLimit)

            shift -= 1
        End While
    End If
End Sub

In the method above the Grids of interest are moved either upwards or downwards so that the correct time is highlighted. PlaceGridInLimitPosition() ensures that a Grid that moves beyond a certain limit is placed accordingly.

Private Sub PlaceGridInLimitPosition(ByRef grd As Grid, ByVal upperLimit As Integer, _
                                     ByVal lowerLimit As Integer)
    If (upperLimit = hourGridUpperLimit) AndAlso (lowerLimit = hourGridLowerLimit) Then
        If (newY >= 280) Then
            Canvas.SetTop(grd, hourGridUpperLimit)
        ElseIf (newY <= -240) Then
            Canvas.SetTop(grd, hourGridLowerLimit)
        End If
    ElseIf (upperLimit = min1GridUpperLimit) AndAlso (lowerLimit = min1GridLowerLimit) Then
        If (newY >= 120) Then
            Canvas.SetTop(grd, min1GridUpperLimit)
        ElseIf (newY <= -160) Then
            Canvas.SetTop(grd, min1GridLowerLimit)
        End If
    ElseIf (upperLimit = min2GridUpperLimit) AndAlso (lowerLimit = min2GridLowerLimit) Then
        If (newY >= 200) Then
            Canvas.SetTop(grd, min2GridUpperLimit)
        ElseIf (newY <= -240) Then
            Canvas.SetTop(grd, min2GridLowerLimit)
        End If
    End If
End Sub

The method TimeKeeper_Tick() handles the Tick event of a DispatcherTimer object, whose Interval property is set to 1 sec, and ensures that the correct time is highlighted when time changes.

Private Sub TimeKeeper_Tick(ByVal sender As Object, ByVal e As EventArgs)
    GetTime(currHour, currMin1, currMin2)

    ' Set new hour.
    If (currentHour <> currHour) Then
        DisplayNewTime(hourCanvas, hourGridLowerLimit, hourGridUpperLimit)
        currentHour = currHour
    End If

    ' Set new first part of minutes.
    If (currentMinute_1 <> currMin1) Then
        DisplayNewTime(min1Canvas, min1GridLowerLimit, min1GridUpperLimit)
        currentMinute_1 = currMin1
    End If

    ' Set new second part of minutes.   
    If (currentMinute_2 <> currMin2) Then
        DisplayNewTime(min2Canvas, min2GridLowerLimit, min2GridUpperLimit)
        currentMinute_2 = currMin2
    End If
End Sub

DisplayNewTime() causes the execution of the animation that creates the scrolling effect.

Private Sub DisplayNewTime(ByRef cnv As Canvas, ByVal lowerLimit As Integer, _
                           ByVal upperLimit As Integer)
    For Each grd As Grid In cnv.Children
        initY = Canvas.GetTop(grd)

        If (initY <= upperLimit) Then
            dblGridAnim.Duration = TimeSpan.FromMilliseconds(1)
            dblGridAnim.To = lowerLimit
            dblGridAnim.FillBehavior = FillBehavior.HoldEnd
            grd.BeginAnimation(Canvas.TopProperty, dblGridAnim)
            newY = initY - gridHeight

            dblGridAnim.Duration = TimeSpan.FromMilliseconds(800)
            dblGridAnim.To = newY
            dblGridAnim.FillBehavior = FillBehavior.HoldEnd
            grd.BeginAnimation(Canvas.TopProperty, dblGridAnim)
        End If
End Sub


That's it. I hope you picked up something useful from this article. If there are any bugs kindly let me know.


  • 16th May, 2012: Initial post


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


About the Author

Meshack Musundi
Software Developer
Kenya Kenya
Meshack is a software developer with a passion for WPF.


  • CodeProject MVP 2013
  • CodeProject MVP 2012

You may also be interested in...

Comments and Discussions

Questiontnx dude Pin
Mani_Kish24-May-12 10:26
memberMani_Kish24-May-12 10:26 
AnswerRe: tnx dude Pin
Meshack Musundi24-May-12 22:50
mvpMeshack Musundi24-May-12 22:50 

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.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.171114.1 | Last Updated 17 May 2012
Article Copyright 2012 by Meshack Musundi
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid