Winsmarts.com

Microsoft MVP

MVP Logo

Awarded the Microsoft MVP Award.

Hosted By

blah!bLaH!BLOG!!

WPF: A ControlTemplate for an Analog Clock

Posted on 3/5/2007 @ 1:21 AM in #WPF | 2 comments | 6940 views


This post is in continuation to an explanation on WPF Templates.

1. ControlTemplate - You use this, when you want to completely redefine the visual appearance of any control. Say, you don't want a radiobutton to look like a radiobutton - you want it to look like a smiley instead. Smiling means Checked, and Frowning means Unchecked. You could easily acheive this using ControlTemplate.

2. ItemsPanelTemplate - Is a rather simple kind of template, it lets you control the appearance of the "ItemsPanel" property defined by "ItemsControl" on elements such as ListBox or ComboBox.

3. DataTemplate - is probably the most common kind of template you will use. It lets you change how "Content" is rendered on any control. So if you have an object called "Customer" and you want to define a standard look and feel for "Customer" - you'd use DataTemplate.


(Recommended reading - What is a ControlTemplate before reading this blogpost).

Okay, check this clock out -

If you wish to use it with the simplicity of this code -

<Grid.Resources>

  <ObjectDataProvider x:Key="dateTime" ObjectType="{x:Type s:DateTime}"/>

</Grid.Resources>

<Control Template="{StaticResource clockTemplate}"

         Width="120" Height="108"

         DataContext="{Binding Path=Now, Source={StaticResource dateTime}}">

</Control>

</Grid>

... simply use the following ControlTemplate -

<ControlTemplate x:Key="clockTemplate">

  <Grid>

      <Grid.Resources>

        <custom:HourToAngle x:Key="hourToAngle"/>

        <custom:MinuteToAngle x:Key="minuteToAngle"/>

      </Grid.Resources>

      <Ellipse Width="108" Height="108" StrokeThickness="3">

        <Ellipse.Stroke>

          <LinearGradientBrush>

            <GradientStop Color="LightBlue" Offset="0" />

            <GradientStop Color="DarkBlue" Offset="1" />

          </LinearGradientBrush>

        </Ellipse.Stroke>

      </Ellipse>

      <Ellipse VerticalAlignment="Center" HorizontalAlignment="Center" Width="104" Height="104" Fill="LightBlue" StrokeThickness="3">

        <Ellipse.Stroke>

          <LinearGradientBrush>

            <GradientStop Color="DarkBlue" Offset="0" />

            <GradientStop Color="LightBlue" Offset="1" />

          </LinearGradientBrush>

        </Ellipse.Stroke>

      </Ellipse>

      <Canvas Width="102" Height="102">

        <Ellipse Width="8" Height="8" Fill="Black" Canvas.Top="46" Canvas.Left="46" />

        <Rectangle Canvas.Top="5" Canvas.Left="48" Fill="Black" Width="4" Height="8">

          <Rectangle.RenderTransform>

            <RotateTransform CenterX="2" CenterY="46" Angle="0" />

          </Rectangle.RenderTransform>

        </Rectangle>

        <Rectangle Canvas.Top="5" Canvas.Left="49" Fill="Black" Width="2" Height="6">

          <Rectangle.RenderTransform>

            <RotateTransform CenterX="2" CenterY="46" Angle="30" />

          </Rectangle.RenderTransform>

        </Rectangle>

        <Rectangle Canvas.Top="5" Canvas.Left="49" Fill="Black" Width="2" Height="6">

          <Rectangle.RenderTransform>

            <RotateTransform CenterX="2" CenterY="46" Angle="60" />

          </Rectangle.RenderTransform>

        </Rectangle>

        <Rectangle Canvas.Top="5" Canvas.Left="48" Fill="Black" Width="4" Height="8">

          <Rectangle.RenderTransform>

            <RotateTransform CenterX="2" CenterY="46" Angle="90" />

          </Rectangle.RenderTransform>

        </Rectangle>

        <Rectangle Canvas.Top="5" Canvas.Left="49" Fill="Black" Width="2" Height="6">

          <Rectangle.RenderTransform>

            <RotateTransform CenterX="2" CenterY="46" Angle="120" />

          </Rectangle.RenderTransform>

        </Rectangle>

        <Rectangle Canvas.Top="5" Canvas.Left="49" Fill="Black" Width="2" Height="6">

          <Rectangle.RenderTransform>

            <RotateTransform CenterX="2" CenterY="46" Angle="150" />

          </Rectangle.RenderTransform>

        </Rectangle>

        <Rectangle Canvas.Top="5" Canvas.Left="48" Fill="Black" Width="4" Height="8">

          <Rectangle.RenderTransform>

            <RotateTransform CenterX="2" CenterY="46" Angle="180" />

          </Rectangle.RenderTransform>

        </Rectangle>

        <Rectangle Canvas.Top="5" Canvas.Left="49" Fill="Black" Width="2" Height="6">

          <Rectangle.RenderTransform>

            <RotateTransform CenterX="2" CenterY="46" Angle="210" />

          </Rectangle.RenderTransform>

        </Rectangle>

        <Rectangle Canvas.Top="5" Canvas.Left="49" Fill="Black" Width="2" Height="6">

          <Rectangle.RenderTransform>

            <RotateTransform CenterX="2" CenterY="46" Angle="240" />

          </Rectangle.RenderTransform>

        </Rectangle>

        <Rectangle Canvas.Top="5" Canvas.Left="48" Fill="Black" Width="4" Height="8">

          <Rectangle.RenderTransform>

            <RotateTransform CenterX="2" CenterY="46" Angle="270" />

          </Rectangle.RenderTransform>

        </Rectangle>

        <Rectangle Canvas.Top="5" Canvas.Left="49" Fill="Black" Width="2" Height="6">

          <Rectangle.RenderTransform>

            <RotateTransform CenterX="2" CenterY="46" Angle="300" />

          </Rectangle.RenderTransform>

        </Rectangle>

        <Rectangle Canvas.Top="5" Canvas.Left="49" Fill="Black" Width="2" Height="6">

          <Rectangle.RenderTransform>

            <RotateTransform CenterX="2" CenterY="46" Angle="330" />

          </Rectangle.RenderTransform>

        </Rectangle>

 

        <Rectangle x:Name="HourHand" Canvas.Top="21" Canvas.Left="48" Fill="Black" Width="4" Height="30">

          <Rectangle.RenderTransform>

            <RotateTransform x:Name="HourHand2" CenterX="2" CenterY="30" Angle="{Binding Mode=OneWay, Converter={StaticResource hourToAngle}}">

            </RotateTransform>

          </Rectangle.RenderTransform> 

        </Rectangle>

 

        <Rectangle x:Name="MinuteHand" Canvas.Top="6" Canvas.Left="49" Fill="Black" Width="2" Height="45">

          <Rectangle.RenderTransform>

            <RotateTransform CenterX="1" CenterY="45" Angle="{Binding Mode=OneWay, Converter={StaticResource minuteToAngle}}">

            </RotateTransform>

          </Rectangle.RenderTransform>

        </Rectangle>

      </Canvas>

  </Grid>

</ControlTemplate>

Note:


On 9/2/2008 4:49:49 AM Hunsoul said ..
Hi! Great example!
I've a problem with it.
It works, but the clock doesn't refresh at all. It's static.
Why doesn't it get notification from the changed value of Now? Is it work for You?

On 9/2/2008 4:52:09 AM Hunsoul said ..
Hi! Great example!
I've a problem with it.
It works, but the clock doesn't refresh at all. It's static.
Why doesn't it get notification from the changed value of Now? Is it work for You?

Please post your comments:


Your feedback will be submitted for moderation, and will appear after it is approved.

Name:  
Email (optional): Your email address will not be posted.
URL (optional):
Comments: HTML will be ignored, URLs will be converted to hyperlinks  
Enter the text you see in the box:
 

Site designed and maintained by Sahil Malik | All Rights Reserved. ©2007 WinSmarts.com.