Give WPF’s DatePicker some Keyboard Love
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!
# Trackback from Windows Client Developer Roundup for 6/28/2010 on 28/06/2010 4:49 PM
# Trackback from Windows Client Developer Roundup for 6/28/2010 on 28/06/2010 5:07 PM
Comments
# Tom Dudfield
6/08/2010 9:53 PM
I've created a sample with similar keyboard support but using attached properties instead. Let me know what you think..
github.com/.../DatePickerExten
# El Ponderado
4/10/2014 2:43 AM
You could also extend the datepicker and in the derived class add a Handler for the PreviewKeyDownEvent.
public class DatePicker : Microsoft.Windows.Controls.DatePicker
{
public override void OnApplyTemplate()
{
this.AddHandler(DatePicker.PreviewKeyDownEvent, new KeyEventHandler(TextBox_PreviewKeyDown));
base.OnApplyTemplate();
}
private void TextBox_PreviewKeyDown(object sender, KeyEventArgs e)
{
var dp = sender as DatePicker;
if (dp == null) 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));
}
}
}
# fragment
26/11/2014 7:45 PM
Thanks a lot!