22

I want to interpret Enter key as Tab key in whole my WPF application, that is, everywhere in my application when user press Enter I want to focus the next focusable control,except when button is focused. Is there any way to do that in application life circle? Can anyone give me an example?
Thanks a lot!

Dave Clemmer
  • 3,757
  • 12
  • 47
  • 72
Arsen Mkrtchyan
  • 47,086
  • 29
  • 143
  • 178

5 Answers5

39

You can use my EnterKeyTraversal attached property code if you like. Add it to the top-level container on a WPF window and everything inside will treat enter as tab:

<StackPanel my:EnterKeyTraversal.IsEnabled="True">
    ...
</StackPanel>
Matt Hamilton
  • 188,161
  • 60
  • 377
  • 317
  • the problem i am facing is that when the focus comes on a button, i want to execute the command and move on the next tab index. Is it possible to do so?? – Jay Nirgudkar Sep 22 '15 at 11:52
7

Based on Richard Aguirre's answer, which is better than the selected answer for ease of use, imho, you can make this more generic by simply changing the Grid to a UIElement.

To change it in whole project you need to do this

  • In App.xaml.cs:

     protected override void OnStartup(StartupEventArgs e)
     {           
         EventManager.RegisterClassHandler(typeof(UIElement), UIElement.PreviewKeyDownEvent, new KeyEventHandler(Grid_PreviewKeyDown));
         base.OnStartup(e);
     }
    
     private void Grid_PreviewKeyDown(object sender, System.Windows.Input.KeyEventArgs e)
     {
         var uie = e.OriginalSource as UIElement;
    
         if (e.Key == Key.Enter)
         {
             e.Handled = true;
             uie.MoveFocus(
             new TraversalRequest(
             FocusNavigationDirection.Next));
         }
     }
    
  • Compile. And done it. Now you can use enter like tab. Note: This work for elements in the grid

Devin
  • 50
  • 6
Richard Aguirre
  • 335
  • 5
  • 12
4

I got around woodyiii's issue by adding a FrameworkElement.Tag (whose value is IgnoreEnterKeyTraversal) to certain elements (buttons, comboboxes, or anything I want to ignore the enter key traversal) in my XAML. I then looked for this tag & value in the attached property. Like so:

    if (e.Key == Key.Enter)
    {
        if (ue.Tag != null && ue.Tag.ToString() == "IgnoreEnterKeyTraversal")
        {
            //ignore
        }
        else
        {
            e.Handled = true;
            ue.MoveFocus(new TraversalRequest(FocusNavigationDirection.Next));
        }
    }
Mohsen Afshin
  • 12,711
  • 8
  • 63
  • 84
Matt
  • 261
  • 3
  • 3
  • Make sure to do this in the `KeyDown` event and not `PreviewKeyDown` or the caret will not move. Also, you don't specify what `ue` is but at least for me it needs to be `e.Source`. – Conrad May 30 '13 at 19:36
  • 1
    That's good. It works on TextBox if it has Tag="IgnoreEnterKeyTraversal" but I want same thing on ComboBox with IsEditable="true". In that scenario your trick does not work. Can you tell me how can I do that?? – Vishal May 31 '16 at 11:02
0

woodyiii, There is a function in the UIElement called PredictFocus() which by its name know its function, then you can check if that element is enabled or not so as to move the focus to it or not...

0

Here is Matt Hamilton's code, if anyone is wondering since his site is down apparently:

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;
        }
    }
}
Matt Gregory
  • 6,184
  • 5
  • 29
  • 36