Flip Clock

Flip Clock emulates the classic "Flip Clock" style of various alarm clocks and airport signage for a clock using Silverlight on Windows Phone 7.

www.cespage.com/silverlight/wp7tut28.html

Step 1

Start Microsoft Visual Studio 2010 Express for Windows Phone, then Select File then New Project... Select "Visual C#" then "Silverlight for Windows Phone" and then "Windows Phone Application" from Templates, select a Location if you wish, then enter a name for the Project and then click OK, see below:

New Project

Step 2

A Windows Phone application Page named MainPage.xaml should then appear, see below:

MainPage.xaml

Step 3

Select from the Main Menu "Project" then "Add New Item...", and select the "Windows Phone User Control" Template, then change the "Name" to Flip.xaml see below:

Add Flip User Control

Step 4

Add the new User Control to the Project by Clicking on Add, then in the XAML Pane for the Flip.xaml User Control.
Remove d:DesignHeight="480" d:DesignWidth="480" from the <UserControl ...> Tag.
Also remove Background="{StaticResource PhoneChromeBrush}" from <Grid x:Name="LayoutRoot" ...>, see below:

Flip UserControl Attributes

Step 5

While still in the XAML Pane for the Flip.xaml User Control, between the <Grid x:Name="LayoutRoot" Background="#FF1F1F1F"> and </Grid> lines type the following XAML:

<Grid Height="140" Width="140">
  <Grid.Resources>
    <Style x:Key="Text" TargetType="TextBlock">
      <Setter Property="FontFamily" Value="{StaticResource PhoneFontFamilyNormal}"/>
      <Setter Property="FontSize" Value="90"/>
      <Setter Property="Foreground" Value="{StaticResource PhoneBackgroundBrush}"/>
    </Style>
    <Style x:Key="Border" TargetType="Border">
      <Setter Property="CornerRadius" Value="8"/>
      <Setter Property="BorderBrush" Value="{StaticResource PhoneSubtleColor}"/>
      <Setter Property="BorderThickness" Value="1,1,1,1"/>
    </Style>
    <LinearGradientBrush x:Key="BackgroundBrush" EndPoint="0.5,1" StartPoint="0.5,0">
      <GradientStop Color="{StaticResource PhoneForegroundColor}" Offset="1"/>
      <GradientStop Color="{StaticResource PhoneAccentColor}"/>
    </LinearGradientBrush>
    <Storyboard x:Name="FlipAnimation">
      <DoubleAnimationUsingKeyFrames Storyboard.TargetName="BlockFlip" 
        Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)">
        <EasingDoubleKeyFrame Value="1" KeyTime="0">
          <EasingDoubleKeyFrame.EasingFunction>
            <BounceEase EasingMode="EaseOut" Bounces="1" Bounciness="6"/>
          </EasingDoubleKeyFrame.EasingFunction>
        </EasingDoubleKeyFrame>
        <EasingDoubleKeyFrame Value="-1" KeyTime="00:00:00.8">
          <EasingDoubleKeyFrame.EasingFunction>
            <BounceEase EasingMode="EaseOut" Bounces="1" Bounciness="6"/>
          </EasingDoubleKeyFrame.EasingFunction>
        </EasingDoubleKeyFrame>
      </DoubleAnimationUsingKeyFrames>
      <ObjectAnimationUsingKeyFrames Storyboard.TargetName="textBlockFlipTop" 
        Storyboard.TargetProperty="(UIElement.Visibility)">
        <DiscreteObjectKeyFrame KeyTime="0">
          <DiscreteObjectKeyFrame.Value>
            <Visibility>Visible</Visibility>
          </DiscreteObjectKeyFrame.Value>
        </DiscreteObjectKeyFrame>
        <DiscreteObjectKeyFrame KeyTime="00:00:00.4">
          <DiscreteObjectKeyFrame.Value>
            <Visibility>Collapsed</Visibility>
          </DiscreteObjectKeyFrame.Value>
        </DiscreteObjectKeyFrame>
      </ObjectAnimationUsingKeyFrames>
      <ObjectAnimationUsingKeyFrames Storyboard.TargetName="textBlockFlipBottom" 
        Storyboard.TargetProperty="(UIElement.Visibility)">
        <DiscreteObjectKeyFrame KeyTime="0">
          <DiscreteObjectKeyFrame.Value>
            <Visibility>Collapsed</Visibility>
          </DiscreteObjectKeyFrame.Value>
        </DiscreteObjectKeyFrame>
        <DiscreteObjectKeyFrame KeyTime="00:00:00.4">
          <DiscreteObjectKeyFrame.Value>
            <Visibility>Visible</Visibility>
          </DiscreteObjectKeyFrame.Value>
        </DiscreteObjectKeyFrame>
      </ObjectAnimationUsingKeyFrames>
    </Storyboard>
  </Grid.Resources>
  <Grid.RowDefinitions>
    <RowDefinition Height="0.5*"/>
    <RowDefinition Height="0.5*"/>
  </Grid.RowDefinitions>
  <Border Style="{StaticResource Border}" Background="{StaticResource BackgroundBrush}" x:Name="BlockTop">
    <TextBlock Style="{StaticResource Text}" HorizontalAlignment="Center" VerticalAlignment="Top" Text="01" x:Name="textBlockTop"/>
  </Border>
  <Border Style="{StaticResource Border}" Grid.Row="1" x:Name="BlockBottom">
    <Border.Background>
      <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
        <GradientStop Color="{StaticResource PhoneForegroundColor}" />
        <GradientStop Color="{StaticResource PhoneAccentColor}" Offset="1"/>
      </LinearGradientBrush>
    </Border.Background>
    <TextBlock Margin="0,0,0,16" Style="{StaticResource Text}" HorizontalAlignment="Center" VerticalAlignment="Bottom" 
      RenderTransformOrigin="0.5,0" Text="00" x:Name="textBlockBottom"/>
  </Border>
  <Border Style="{StaticResource Border}" Background="{StaticResource BackgroundBrush}" RenderTransformOrigin="0.5,1" x:Name="BlockFlip">
    <Border.RenderTransform>
    <TransformGroup>
      <ScaleTransform/>
      <SkewTransform/>
      <RotateTransform/>
      <TranslateTransform/>
    </TransformGroup>
  </Border.RenderTransform>
  <Grid>
    <TextBlock Style="{StaticResource Text}" HorizontalAlignment="Center" VerticalAlignment="Top" Text="00" 
      x:Name="textBlockFlipTop"/>
    <TextBlock Style="{StaticResource Text}" HorizontalAlignment="Center" VerticalAlignment="Bottom" Visibility="Collapsed" 
      RenderTransformOrigin="0.5,0.5" x:Name="textBlockFlipBottom">
      <TextBlock.RenderTransform>
        <TransformGroup>
          <ScaleTransform ScaleY="-1"/>
          <SkewTransform/>
          <RotateTransform/>
          <TranslateTransform Y="70"/>
          </TransformGroup>
        </TextBlock.RenderTransform>
      </TextBlock>
    </Grid>
  </Border>
</Grid>

XAML:

Flip UserControl XAML View

Design:

Flip UserControl Design View

Step 6

Right Click on the Page or the entry for "Flip.xaml" in Solution Explorer and choose the "View Code" option. In the Code View above "public Flip()" type the following Dependancy Properties, Properties and Methods:

public static readonly DependencyProperty TextPrevProperty =
DependencyProperty.Register("TextPrev", typeof(string),
typeof(Flip), null);

public static readonly DependencyProperty TextNextProperty =
DependencyProperty.Register("TextNext", typeof(string),
typeof(Flip), null);

public string TextPrev
{
  get { return (string)GetValue(TextPrevProperty); }
  set
  {
    SetValue(TextPrevProperty, value);
    textBlockBottom.Text = TextPrev;
    textBlockFlipTop.Text = TextPrev;
  }
}

public string TextNext
{
  get { return (string)GetValue(TextNextProperty); }
  set
  {
    SetValue(TextNextProperty, value);
    textBlockTop.Text = TextNext;
    textBlockFlipBottom.Text = TextNext;
  }
}

public void Value(string source, string target)
{
  TextNext = target;
  TextPrev = source;
  FlipAnimation.Begin();
}

See Below:

Flip UserControl Properties and Methods

Step 7

Select "Build Solution" from the Debug menu, see below:

Build Solution

Step 8

When the Build completes, return to the MainPage Designer View by selecting the "MainPage.xaml" Tab.
In XAML Pane for MainPage.xaml between the <Grid x:Name="ContentGrid" Grid.Row="1"> and </Grid> lines type the following StackPanel XAML:

<StackPanel Height="200" Width="420" 
  HorizontalAlignment="Center" Orientation="Horizontal">

</StackPanel>

XAML:

MainPage XAML Pane

Design:

MainPage Design View

Step 9

Then from the FlipClock Controls section in the Toolbox select the Flip control:

Flip User Control

Step 10

Draw three Flip Controls onto the StackPanel by dragging the Flip Controls from the Toolbox onto the StackPanel, then in the XAML Pane change the <my:Flip ...> lines to the following:

<my:Flip x:Name="Hours"/>
<my:Flip x:Name="Minutes"/>
<my:Flip x:Name="Seconds"/>

XAML:

MainPage XAML Pane

Design:

MainPage Design View

Step 11

Right Click on the Page or the entry for "MainPage.xaml" in Solution Explorer and choose the "View Code" option. In the Code View above "namespace FlipClock" type the following:

using System.Windows.Threading;

Also in the CodeView above "public MainPage()" type the following Declarations:

private DispatcherTimer _timer = new DispatcherTimer();
private int _seconds = DateTime.Now.Second;
private int _minutes = DateTime.Now.Minute;
private int _hours = DateTime.Now.Hour;

See Below:

MainPage Reference and Declarations

Step 12

While still the Code View for MainPage.xaml.cs above "public MainPage()" type the following Event Handler:

private void Timer_Tick(object sender, EventArgs e)
{
  if (_seconds == 59)
  {
    Seconds.Value(_seconds.ToString("00"), 0.ToString("00"));
    _seconds = 0;
    if (_minutes == 59)
    {
      Minutes.Value(_minutes.ToString("00"), 0.ToString("00"));
      _minutes = 0;
      if (_hours == 23)
      {
        Hours.Value(_hours.ToString("00"), 0.ToString("00"));
        _hours = 0;
      }
      else
      {
        Hours.Value(_hours.ToString("00"), (_hours + 1).ToString("00"));
        _hours += 1;
      }
    }
    else
    {
      Minutes.Value(_minutes.ToString("00"), (_minutes + 1).ToString("00"));
      _minutes += 1;
    }
  }
  else
  {
    Seconds.Value(_seconds.ToString("00"), (_seconds + 1).ToString("00"));
    _seconds += 1;
  }
}

See Below:

MainPage Event Handler

Step 13

While still in the Code View in the "public MainPage()" Constructor below "InitializeComponent();" type the following:

PageTitle.Text = "flip clock";
Seconds.TextPrev = _seconds.ToString("00");
Minutes.TextPrev = _minutes.ToString("00");
Hours.TextPrev = _hours.ToString("00");
_timer.Tick += Timer_Tick;
_timer.Interval = TimeSpan.FromSeconds(1);
_timer.Start();

See Below:

MainPage Constructor

Step 14

Save the Project as you have now finished the Windows Phone Silverlight application. Select the Windows Phone Emulator option then Select Debug then Start Debugging or click on Start Debugging:

Start Debugging

After you do, the following will appear in the Windows Phone Emulator after it has been loaded:

Application Running

Step 15

You can then Stop the application by selecting the Visual Studio 2010 application window and clicking on the Stop Debugging button:

Stop Debugging

This is a simple Flip Clock using a Flip UserControl, it would be possible to use the Flip user control to display text such as the previously mentioned Airport displays for example - you can change the control to look even more like a classic flip clock or anything else - make it your own!