Display a label and analog clock on screen, they should be updated “live” with the time.
/// <summary>
/// XAML Markup Extension to bind dependency property (DateTime or String)
/// to the current date and time (updated each second)
/// </summary>
public class NowExtension : MarkupExtension
{
#region State
// default, full date format (current culture)
private readonly string m_format =
CultureInfo.CurrentCulture.DateTimeFormat.FullDateTimePattern;
// for empty constructor we return the DateTime
private readonly bool m_returnDate = false;
private DependencyObject m_targetObject;
private DependencyProperty m_targetProperty;
private DispatcherTimer m_timer;
#endregion
#region Constructors
/// <summary>
/// Create new Now Extension that return the
/// current DateTime (DateTime.Now)
/// </summary>
public NowExtension()
{
m_returnDate = true;
}
/// <summary>
/// Create new Now Extension that return the
/// current DateTime formatted (calling ToString
/// with m_format)
/// </summary>
public NowExtension(string format)
{
if (!string.IsNullOrEmpty(format))
{
m_format = format;
}
}
#endregion
/// <summary>
/// Overrides MarkupExtension.ProvideValue to return
/// the current datetime and hook a timer to update the
/// target propery each second
/// (using DispatcherTime with Background priority)
/// </summary>
/// <param name="serviceProvider"></param>
/// <returns></returns>
public override object ProvideValue(IServiceProvider serviceProvider)
{
var targetHelper =
(IProvideValueTarget)
serviceProvider.GetService(typeof(IProvideValueTarget));
m_targetObject =
targetHelper.TargetObject as DependencyObject;
m_targetProperty =
targetHelper.TargetProperty as DependencyProperty;
m_timer = new DispatcherTimer(DispatcherPriority.Background);
m_timer.Interval = TimeSpan.FromSeconds(1);
m_timer.Tick += new EventHandler(m_timer_Tick);
m_timer.Start();
if (m_returnDate)
{
return DateTime.Now;
}
return GetNowValue();
}
protected virtual string GetNowValue()
{
return DateTime.Now.ToString(m_format);
}
void m_timer_Tick(object sender, EventArgs e)
{
if (m_targetObject != null && m_targetProperty != null)
{
object value = GetNowValue();
if (m_returnDate)
{
value = DateTime.Now;
}
m_targetObject.SetValue(m_targetProperty, value);
}
}
}
The first time the ProviderValue is called, we are hooking to the target DependencyObject / DependencyProperty so we will be able to set the property on timer intervals. Then we start a timer (with interval of 1 second) and in that timer Tick event we set the new value to the hooked property, the last line just return the current value for the first time.