Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Moving to next control on Enter keypress in WPF

Tags:

c#

mvvm

wpf

I want to move to the next control when I press the Enter key instead of the Tab key in a WPF MVVM application. How can I achieve this?

like image 505
Kishore Kumar Avatar asked Nov 20 '11 17:11

Kishore Kumar


People also ask

How to skip move focus in textbox?

I have used "tag" property of textbox for skip move focus. i.e. if some time you dont want to move to next control on enter key pressed (in the case of multiline text box where enter is required to create new line). Just set tag property to 1. Show activity on this post.

How to use previewkeydown event in stack panel?

sample solution: using PreviewKeyDown in the stack panel. The Preview... is a bubble up so the event can be handled at a higher level. You may need to handle this differently for different element types, like button it seems should keep the enter key and not change focus on the enter key.

How to bind focus to element in previewkeydown trigger?

First that occured to add trigger to each element that will invoke when PreviewKeyDown fires. Also add Dependency property and bind FrameworkElement that you wont to bring focus at. Within trigger provide setting Focus to binded element.

How to send tab when the user presses enter?

If the user presses ENTER you can call Control.SelectNextControl () or SendKeys.Send (" {TAB}"). :) +5 good answer. :-) this way is proper to achieve your goal. If you think that it is proper why you give me a 2? You know that 1 and 2 are down-votes and 4 and 5 are up-votes, right? :) Thanks for your answer.


2 Answers

Below is an attached property that I've used for just this.

First, example usage:

<TextBox Width="100"          Text="{Binding Name, Mode=TwoWay}"          UI:FocusAdvancement.AdvancesByEnterKey="True" /> 

(UI is the namespace alias for where I've defined the following.)

The attached property:

public static class FocusAdvancement {     public static bool GetAdvancesByEnterKey(DependencyObject obj)     {         return (bool)obj.GetValue(AdvancesByEnterKeyProperty);     }      public static void SetAdvancesByEnterKey(DependencyObject obj, bool value)     {         obj.SetValue(AdvancesByEnterKeyProperty, value);     }      public static readonly DependencyProperty AdvancesByEnterKeyProperty =         DependencyProperty.RegisterAttached("AdvancesByEnterKey", typeof(bool), typeof(FocusAdvancement),          new UIPropertyMetadata(OnAdvancesByEnterKeyPropertyChanged));      static void OnAdvancesByEnterKeyPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)     {         var element = d as UIElement;         if(element == null) return;          if ((bool)e.NewValue) element.KeyDown += Keydown;         else element.KeyDown -= Keydown;     }      static void Keydown(object sender, KeyEventArgs e)     {         if(!e.Key.Equals(Key.Enter)) return;          var element = sender as UIElement;         if(element != null) element.MoveFocus(new TraversalRequest(FocusNavigationDirection.Next));     } } 

You also said "instead of tab," so I'm wondering if you want to suppress the ability to use tab in the usual way. I'd advise against it, as it is a common, well known paradigm, but if that is the case, you can add a PreviewKeyDown handler in the attached property, check for the tab key, and set Handled = true for the event args.

like image 153
Jay Avatar answered Sep 28 '22 12:09

Jay


If you only want it to work for a few text boxes, Jay's answer is best.

If you want your whole application to work that way, makwana.a's answer is better but can be improved.

Below is my modification of makwana.a's answer, which I have used in numerous applications. It also includes support for moving to the next control via enter if the active control is a check box. Instead of using the tag property to decide whether or not the focus should move, I used the AcceptsReturn property of the text box. I did this because it defaults to false and will only be set to true on multi-line text boxes. In that case, you won't want the focus to move to the next control on enter anyway.

Declare these event handlers in the OnStartup void of App.xaml

        EventManager.RegisterClassHandler(typeof(TextBox), TextBox.KeyDownEvent, new KeyEventHandler(TextBox_KeyDown));         EventManager.RegisterClassHandler(typeof(CheckBox), CheckBox.KeyDownEvent, new KeyEventHandler(CheckBox_KeyDown)); 

Here are the rest of the methods needed to make it work application wide.

    void TextBox_KeyDown(object sender, KeyEventArgs e)     {         if (e.Key == Key.Enter & (sender as TextBox).AcceptsReturn == false) MoveToNextUIElement(e);     }      void CheckBox_KeyDown(object sender, KeyEventArgs e)     {         MoveToNextUIElement(e);         //Sucessfully moved on and marked key as handled.         //Toggle check box since the key was handled and         //the checkbox will never receive it.         if (e.Handled == true)         {             CheckBox cb = (CheckBox)sender;             cb.IsChecked = !cb.IsChecked;         }       }      void MoveToNextUIElement(KeyEventArgs e)     {         // Creating a FocusNavigationDirection object and setting it to a         // local field that contains the direction selected.         FocusNavigationDirection focusDirection = FocusNavigationDirection.Next;          // MoveFocus takes a TraveralReqest as its argument.         TraversalRequest request = new TraversalRequest(focusDirection);          // Gets the element with keyboard focus.         UIElement elementWithFocus = Keyboard.FocusedElement as UIElement;          // Change keyboard focus.         if (elementWithFocus != null)         {             if (elementWithFocus.MoveFocus(request)) e.Handled = true;         }     } 

Edit

I updated the code to mark the keystroke as handled if the movement was successful and also toggle the checkbox since the key was handled and will no longer reach it.

like image 29
StillLearnin Avatar answered Sep 28 '22 10:09

StillLearnin