It’s possible to implement an analogic clock in WPF simply using the RotateTransform class and just a few line of code.
In this example I didn’t develop a sophisticate user interface, I just wanted to show you the concept.
First of all we define a class that will represent our clock model, it will have 3 public property :
- SecondsDegrees
- MinutesDegrees
- HoursDegrees
This read only properties will return the actual time. I chose to return a value already converted in degrees ( from 0 to 359), in this way it’s faster and easier, but if you want you can return the standard format and use a converter in the binding class.
We also need to notify the control to refresh the value each second,we do this by implementing a timer class and the INotifyPropertyChanged interface.
Here is the code:
| using System; using System.ComponentModel; using System.Timers; namespace TheClock { public class ClockClass : INotifyPropertyChanged { private Timer timer = new Timer(1000); public ClockClass() { timer.Elapsed += new ElapsedEventHandler((sender,e) => OnPropertyChanged(null) ); timer.Start(); } public int SecondsDegrees { get { return DateTime.Now.Second * 6; } } public int MinutesDegrees { get { return DateTime.Now.Minute * 6; } } public int HoursDegrees { get { return DateTime.Now.Hour * 30 + (int)(DateTime.Now.Minute / 2); } } #region INotifyPropertyChanged Members private void OnPropertyChanged(string property) { if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(property)); } public event PropertyChangedEventHandler PropertyChanged; #endregion } } |
Now adding the RotateTransform class to the RenderTransform collection of each arm of the clock and binding the angle to the previous class we get the result we expected…
| <UserControl x:Class="TheClock.Clock" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Height="300" Width="300"> <Canvas> <Line Canvas.Top="10" Canvas.Left="150" X1="0" Y1="30" X2="0" Y2="140" RenderTransformOrigin=".5,1" Stroke="Black" StrokeThickness="4"> <Line.RenderTransform> <RotateTransform Angle="{Binding MinutesDegrees}"/> </Line.RenderTransform> </Line> <Line Canvas.Top="10" Canvas.Left="150" X1="0" Y1="60" X2="0" Y2="140" RenderTransformOrigin=".5,1" Stroke="Black" StrokeThickness="8"> <Line.RenderTransform> <RotateTransform Angle="{Binding HoursDegrees}"/> </Line.RenderTransform> </Line> <Line Canvas.Top="10" Canvas.Left="150" X1="0" Y1="0" X2="0" Y2="140" RenderTransformOrigin=".5,1" Stroke="Black" StrokeThickness="2"> <Line.RenderTransform> <RotateTransform Angle="{Binding SecondsDegrees}"/> </Line.RenderTransform> </Line> </Canvas> </UserControl> |
and the user control’s code behind:
| using System.Windows.Controls; namespace TheClock { /// <summary> /// Interaction logic for Clock.xaml /// </summary> public partial class Clock : UserControl { public Clock() { InitializeComponent(); this.DataContext = new ClockClass(); } } } |
Just with a few code we got a working analogic clock…