namespace Common.UI.Controls { using System; using System.Timers; using System.Windows; using System.Windows.Controls; public partial class Clock : Label { const string DEFAULT_FORMAT = "hh\\:mm\\:ss"; public static readonly DependencyProperty TimerProperty = DependencyProperty.Register( name: nameof(Timer) , propertyType: typeof(Timer) , ownerType: typeof(Clock) , typeMetadata: new FrameworkPropertyMetadata(TimerPropertyChanged)); public static readonly DependencyProperty FormatProperty = DependencyProperty.Register( name: nameof(Format) , propertyType: typeof(string) , ownerType: typeof(Clock) , typeMetadata: new FrameworkPropertyMetadata(DEFAULT_FORMAT)); public Clock() => this.InitializeComponent(); public Timer Timer { get => GetValue(TimerProperty) as Timer; set => SetValue(TimerProperty, value); } public string Format { get => GetValue(FormatProperty) as string; set => SetValue(FormatProperty, value); } private DateTime? startTime; private void Timer_Elapsed(Object sender, ElapsedEventArgs args) { App.InvokeAsync(() => { if (this.startTime is null) { this.Opacity = 1; this.startTime = args.SignalTime; } var timespan = args.SignalTime - this.startTime.Value; this.Content = timespan.ToString(this.Format ?? DEFAULT_FORMAT); }); } private void BindTimer(object value) { App.InvokeAsync(() => { if (value is Timer timer) { timer.Elapsed += this.Timer_Elapsed; } this.startTime = null; this.Opacity = 0.3; this.Content = new TimeSpan().ToString(this.Format ?? DEFAULT_FORMAT); }); } private void UnbindTimer(object value) { App.InvokeAsync(() => { if (value is Timer timer) { timer.Elapsed -= this.Timer_Elapsed; } this.startTime = null; this.Opacity = 0.3; this.Content = new TimeSpan().ToString(this.Format ?? DEFAULT_FORMAT); }); } private static void TimerPropertyChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs args) { if (dependencyObject is Clock clock) { clock.UnbindTimer(args.OldValue); clock.BindTimer(args.NewValue); } } } }