Updated! As suggested by Eric Burke in the comments, I'm now handling the "Unloaded" event and unhooking the event handlers there, so the elements are properly cleaned up by the garbage collector. Thanks Eric!

A while ago I posted about a trick to make your WPF applications treat the enter key as a tab, and shift focus to the next available control. Paul commented that it should be possible to do that using an attached property, and I agreed, but didn't know how.

Well, now I do.

I'll post the full code for the property itself below, but first, its usage. Firstly you'll need to add an xmlns declaration to the top of your form pointing to the class' namespace. Usually this is just the namespace of your application, like WpfApplication1. I like to call this XML namespace "my". So your window's declaration ends up looking like:

<Window x:Class="WpfApplication1.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:my="clr-namespace:WpfApplication1"
    Title="Window1">

Next you want to find the container control (usually a Grid or StackPanel) in which all your data-entry controls live, and add the attached property to it, like this:

<StackPanel my:EnterKeyTraversal.IsEnabled="True">

Now all the controls within that StackPanel will treat the Enter key as a tab! Once the focus shifts out of the StackPanel the Enter key reverts to its normal behaviour, which is nice because the very next control will probably be an "OK" button, and the user will want to be able to press Enter to click it.

Here's the complete class declaration to give you the EnterKeyTraversal.IsEnabled property. Have fun!

public class EnterKeyTraversal { public static bool GetIsEnabled(DependencyObject obj) { return (bool)obj.GetValue(IsEnabledProperty); } public static void SetIsEnabled(DependencyObject obj, bool value) { obj.SetValue(IsEnabledProperty, value); } static void ue_PreviewKeyDown(object sender, System.Windows.Input.KeyEventArgs e) { var ue = e.OriginalSource as FrameworkElement; if (e.Key == Key.Enter) { e.Handled = true; ue.MoveFocus(new TraversalRequest(FocusNavigationDirection.Next)); } } private static void ue_Unloaded(object sender, RoutedEventArgs e) { var ue = sender as FrameworkElement; if (ue == null) return; ue.Unloaded -= ue_Unloaded; ue.PreviewKeyDown -= ue_PreviewKeyDown; } public static readonly DependencyProperty IsEnabledProperty = DependencyProperty.RegisterAttached("IsEnabled", typeof(bool),

typeof(EnterKeyTraversal), new UIPropertyMetadata(false, IsEnabledChanged)); static void IsEnabledChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var ue = d as FrameworkElement; if (ue == null) return; if ((bool)e.NewValue) { ue.Unloaded += ue_Unloaded; ue.PreviewKeyDown += ue_PreviewKeyDown; } else { ue.PreviewKeyDown -= ue_PreviewKeyDown; } } }