I’ve just started using the DatePicker control from the WPF Toolkit for .NET 3.5 SP1. DatePicker is built into .NET 4, but for reasons I’ve already explained, we’re stuck on 3.5 for the time being.

Anyway, the DatePicker is a simple enough control. It has a TextBox where you can type in a date, and a button that pops open a calendar if you prefer to use the mouse.

For us keyboard junkies, though, it’s lacking a few little niceties. For example, I want to be able to use the up- and down-arrow keys to increment and decrement the date. I’d also like to be able to jump straight to today’s date using Ctrl+D – a habit I picked up from using Microsoft Money for many years.

So here’s some code that will introduce those keyboard shortcuts into all the DatePickers in your application. Basically I’m using the EventManager class to set up a “global event handler” for the PreviewKeyDown event on the DatePicker.

First, override the OnStartup method in your App class (in App.xaml.cs):

protected override void OnStartup(StartupEventArgs e)
{
    base.OnStartup(e);

    EventManager.RegisterClassHandler(typeof(DatePicker),
        DatePicker.PreviewKeyDownEvent,
        new KeyEventHandler(DatePicker_PreviewKeyDown));

Next, define your “DatePicker_PreviewKeyDown” method in the same class:

private void DatePicker_PreviewKeyDown(object sender, KeyEventArgs e)
{
    var dp = sender as DatePicker;
    if (dp == null) return;

    if (e.Key == Key.D && Keyboard.Modifiers == ModifierKeys.Control)
    {
        e.Handled = true;
        dp.SetValue(DatePicker.SelectedDateProperty, DateTime.Today);
        return;
    }

    if (!dp.SelectedDate.HasValue) return;

    var date = dp.SelectedDate.Value;
    if (e.Key == Key.Up)
    {
        e.Handled = true;
        dp.SetValue(DatePicker.SelectedDateProperty, date.AddDays(1));
    }
    else if (e.Key == Key.Down)
    {
        e.Handled = true;
        dp.SetValue(DatePicker.SelectedDateProperty, date.AddDays(-1));
    }
}

Note that I’m using “dp.SetValue” in this code rather than just assigning a value directly to dp.SelectedDate. The reason I’m doing it this way is that the SelectedDate value might be data-bound. If it is, assigning a value to it directly will “cancel out” the binding.

The “global event handler” trick with EventManager is a very powerful and flexible way to add application-wide behaviour to any control. Give it a try!