I want to know how to display current date and time on a WPF statusbar.
I know this is too basic a question, but I am new to .net WPF, and I know this can be done in a Form application easily.
Thanks in advance.
Ting
I want to know how to display current date and time on a WPF statusbar.
I know this is too basic a question, but I am new to .net WPF, and I know this can be done in a Form application easily.
Thanks in advance.
Ting
Create a wpf project. In your MainWindow.xaml add the StatusBar and handle Loaded event of window.
<Window
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        x:Class="WpfApp1.MainWindow"
        Title="MainWindow" Height="450" Width="800" Loaded="Window_Loaded">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <StatusBar Grid.Row="1">
            <TextBlock x:FieldModifier="private" x:Name="myDateTime"/>
        </StatusBar>
    </Grid>
</Window>
In the MainWindow.xaml.cs add the following namespaces (if they are not exist):
using System;
using System.Windows;
using System.Windows.Threading;
And in the Loaded enevt handler you can use DispatcherTimer for update textblock text property every second:
private void Window_Loaded(object sender, RoutedEventArgs e)
{
   DispatcherTimer timer = new DispatcherTimer(TimeSpan.FromSeconds(1), DispatcherPriority.Normal, (object s, EventArgs ev) =>
   {
      this.myDateTime.Text = DateTime.Now.ToString("yyyy/MM/dd hh:mm:ss");
   }, this.Dispatcher);
   timer.Start();
}
Also there are a lot of examples for customize wpf controls using Template and Style properties. just search for it.
and many more.
Also you can implement your custom WPFTimer. This simple implementation get you an idea for do this.
public class WPFTimer : TextBlock
{
   #region static
   public static readonly DependencyProperty IntervalProperty = DependencyProperty.Register("Interval", typeof(TimeSpan), typeof(WPFTimer), new PropertyMetadata(TimeSpan.FromSeconds(1), IntervalChangedCallback));
   public static readonly DependencyProperty IsRunningProperty = DependencyProperty.Register("IsRunning", typeof(bool), typeof(WPFTimer), new PropertyMetadata(false, IsRunningChangedCallback));
   private static void IntervalChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
   {
      WPFTimer wpfTimer = (WPFTimer)d;
      wpfTimer.timer.Interval = (TimeSpan)e.NewValue;
   }
   private static void IsRunningChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
   {
      WPFTimer wpfTimer = (WPFTimer)d;
      wpfTimer.timer.IsEnabled = (bool)e.NewValue;
   }
   #endregion
   private readonly DispatcherTimer timer;
   [Category("Common")]
   public TimeSpan Interval
   {
      get
      {
         return (TimeSpan)this.GetValue(IntervalProperty);
      }
      set
      {
         this.SetValue(IntervalProperty, value);
      }
   }
   [Category("Common")]
   public bool IsRunning
   {
      get
      {
         return (bool)this.GetValue(IsRunningProperty);
      }
      set
      {
         this.SetValue(IsRunningProperty, value);
      }
   }
   public WPFTimer()
   {
      this.timer = new DispatcherTimer(this.Interval, DispatcherPriority.Normal,this.Timer_Tick ,this.Dispatcher);
      this.timer.IsEnabled = false;
   }
   private void Timer_Tick(object sender, EventArgs e)
   {
      this.SetValue(TextProperty, DateTime.Now.ToString("yyyy/MM/dd hh:mm:ss"));
   }
}
And now you have a control that can use it in the designer.
<Window
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfApp1"
        x:Class="WpfApp1.MainWindow"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <StatusBar Grid.Row="1">
            <local:WPFTimer IsRunning="True"/>
        </StatusBar>
    </Grid>
</Window>
You can do it this way, using wpf animation and binding, and no background code :)
<Window x:Class="WpfApp6.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:system="clr-namespace:System;assembly=System.Runtime"
        mc:Ignorable="d"
        Title="MainWindow"
        Height="450"
        Width="800">
    <Grid>
        <Grid.Resources>
            <!--Set x: share to get the latest every time-->
            <system:DateTime x:Key="DateTime"
                                x:Shared="False" />
            <Storyboard x:Key="Storyboard">
                <!--Use keyframe animation to update datetime -->
                <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="DataContext"
                                                Duration="0:0:1"
                                                RepeatBehavior="Forever"
                                                AutoReverse="False">
                    <DiscreteObjectKeyFrame KeyTime="50%"
                                            Value="{StaticResource DateTime}" />
                </ObjectAnimationUsingKeyFrames>
            </Storyboard>
        </Grid.Resources>
        <!--Get datetime from DataContext-->
        <TextBlock Text="{Binding RelativeSource={RelativeSource Self},Path=DataContext.Now}"
                    DataContext="{StaticResource DateTime}">
            <TextBlock.Triggers>
                <EventTrigger RoutedEvent="Loaded">
                    <BeginStoryboard Storyboard="{StaticResource Storyboard}" />
                </EventTrigger>
            </TextBlock.Triggers>
        </TextBlock>
    </Grid>
</Window>
or like this,a real clock
<Window x:Class="WpfApp6.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:system="clr-namespace:System;assembly=System.Runtime"
        mc:Ignorable="d"
        Title="MainWindow"
        Height="450"
        Width="800">
    <Window.Resources>
        <FrameworkElement x:Key="time" Tag="{x:Static system:DateTime.Now}" />
        <TransformGroup x:Key="transformHour">
            <TranslateTransform X="{Binding Source={StaticResource time},Path=Tag.Hour}"
                                Y="{Binding Source={StaticResource time},Path=Tag.Minute}" />
            <MatrixTransform Matrix="30 0 0.5 0 0 0" />
        </TransformGroup>
        <TransformGroup x:Key="transformMinute">
            <TranslateTransform X="{Binding Source={StaticResource time},Path=Tag.Minute}"
                                Y="{Binding Source={StaticResource time},Path=Tag.Second}" />
            <MatrixTransform Matrix="6 0 0.1 0 0 0" />
        </TransformGroup>
        <TransformGroup x:Key="transformSecond">
            <TranslateTransform X="{Binding Source={StaticResource time},Path=Tag.Second}" />
            <MatrixTransform Matrix="6 0 0 0 0 0" />
        </TransformGroup>
        <Style TargetType="{x:Type Path}">
            <Setter Property="Stroke"
                    Value="{DynamicResource {x:Static SystemColors.WindowTextBrushKey}}" />
            <Setter Property="StrokeThickness" Value="3" />
            <Setter Property="StrokeDashCap" Value="Triangle" />
        </Style>
    </Window.Resources>
    <Viewbox>
        <Canvas Width="200" Height="200">
            <Canvas.RenderTransform>
                <TranslateTransform X="100" Y="100" />
            </Canvas.RenderTransform>
            <Path Data="M 0 -90 A 90 90 0 1 1 -0.01 -90"
                StrokeDashArray="0 3.14157" />
            <Path Data="M 0 -90 A 90 90 0 1 1 -0.01 -90"
                StrokeDashArray="0 7.854"
                StrokeThickness="6" />
            <Border Background="LightBlue" Width="10" Height="80" RenderTransformOrigin="0.5 0">
                <Border.RenderTransform>
                    <TransformGroup>
                        <RotateTransform x:Name="bor_Second"
                                        Angle="{Binding Source={StaticResource transformSecond},Path=Value.OffsetX}" />
                        <RotateTransform Angle="180" />
                    </TransformGroup>
                </Border.RenderTransform>
            </Border>
            <Border Background="LightGreen" Width="10" Height="60" RenderTransformOrigin="0.5 0">
                <Border.RenderTransform>
                    <TransformGroup>
                        <RotateTransform x:Name="bor_Minute"
                                        Angle="{Binding Source={StaticResource transformMinute},Path=Value.OffsetX}" />
                        <RotateTransform Angle="180" />
                    </TransformGroup>
                </Border.RenderTransform>
            </Border>
            <Border Background="LightGray" Width="10" Height="40" RenderTransformOrigin="0.5 0">
                <Border.RenderTransform>
                    <TransformGroup>
                        <RotateTransform x:Name="bor_Hour"
                                        Angle="{Binding Source={StaticResource transformHour},Path=Value.OffsetX}" />
                        <RotateTransform Angle="180" />
                    </TransformGroup>
                </Border.RenderTransform>
            </Border>
        </Canvas>
    </Viewbox>
    <Window.Triggers>
        <EventTrigger RoutedEvent="Loaded">
            <BeginStoryboard>
                <Storyboard>
                    <DoubleAnimation Storyboard.TargetName="bor_Hour"
                                    Storyboard.TargetProperty="Angle"
                                    IsAdditive="True"
                                    Duration="12:0:0"
                                    From="0" To="360"
                                    RepeatBehavior="Forever" />
                    <DoubleAnimation Storyboard.TargetName="bor_Minute"
                                    Storyboard.TargetProperty="Angle"
                                    IsAdditive="True"
                                    Duration="1:0:0"
                                    From="0" To="360"
                                    RepeatBehavior="Forever" />
                    <DoubleAnimation Storyboard.TargetName="bor_Second"
                                    Storyboard.TargetProperty="Angle"
                                    IsAdditive="True"
                                    Duration="0:1:0"
                                    From="0"
                                    To="360"
                                    RepeatBehavior="Forever" />
                </Storyboard>
            </BeginStoryboard>
        </EventTrigger>
    </Window.Triggers>
</Window>