Press Enter to move to next control

ravi kumar 331 Reputation points
2020-12-17T09:30:39.71+00:00

I have a few TextBox on the WinForm. I would like the focus to move to the next control when Enter key is pressed? Whenever a textbox gains control, it will also select the text, so that any editing will replace the current one.

"but if the control is on buttons and link labels it should fire the keypress event"

What is the best way to do this?,
49093-form.png

Windows Forms
Windows Forms
A set of .NET Framework managed libraries for developing graphical user interfaces.
1,820 questions
Visual Studio
Visual Studio
A family of Microsoft suites of integrated development tools for building applications for Windows, the web and mobile devices.
4,571 questions
C#
C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
10,191 questions
0 comments No comments
{count} votes

Accepted answer
  1. Karen Payne MVP 35,026 Reputation points
    2020-12-17T10:56:45.427+00:00

    Hello @ravi kumar

    The following code gets a TextBox controls into a list, iterates the list and subscribes each TextBox to an anonymous KeyDown event which when ENTER is detected moves to the next control, other control types act normally.

    Form code

    Note thatTextBoxList is a language extension method which may appear like overkill (see the class below for the definition) but the second way below will not find all controls on a form. So you have two choices to pick from

    Option 1

    public partial class Form1 : Form  
    {  
        public Form1()  
        {  
            InitializeComponent();  
            Shown += Form1_Shown;  
        }  
      
        private void Form1_Shown(object sender, EventArgs e)  
        {  
            this.TextBoxList().ForEach(textBox => textBox.KeyDown += (s,ea) => {  
                if (ea.KeyCode == Keys.Enter)  
                {  
                    ea.SuppressKeyPress = true;  
                    SelectNextControl(ActiveControl, true, true, true, true);  
                }  
            });  
        }  
    }  
    

    Option 2

    public partial class Form1 : Form  
    {  
        public Form1()  
        {  
            InitializeComponent();  
            Shown += Form1_Shown;  
        }  
      
        private void Form1_Shown(object sender, EventArgs e)  
        {  
            foreach (Control control in Controls)  
            {  
                if (control is TextBox textBox)  
                {  
                    textBox.KeyDown += (s, ea) =>  
                    {  
                        if (ea.KeyCode != Keys.Enter) return;  
                        ea.SuppressKeyPress = true;  
                        SelectNextControl(ActiveControl, true, true, true, true);  
                    };  
                }  
            }  
        }  
    }  
    

    Language extension class

    Note there are wrappers for common controls

    using System.Collections.Generic;  
    using System.Linq;  
    using System.Windows.Forms;  
      
    namespace MoveToNextControl.Extensions  
    {  
        public static class GenericControlExtensions  
        {  
            /// <summary>  
            /// Get a collection of a specific type of control from a control or form.  
            /// </summary>  
            /// <typeparam name="T">Type of control</typeparam>  
            /// <param name="control">Control to traverse</param>  
            /// <returns>IEnumerable of T</returns>  
            public static IEnumerable<T> Descendants<T>(this Control control) where T : class  
            {  
                foreach (Control child in control.Controls)  
                {  
                    T thisControl = child as T;  
                    if (thisControl != null)  
                    {  
                        yield return (T)thisControl;  
                    }  
      
                    if (child.HasChildren)  
                    {  
                        foreach (T descendant in Descendants<T>(child))  
                        {  
                            yield return descendant;  
                        }  
                    }  
                }  
      
            }  
            /// <summary>  
            /// Get all TextBoxes in a control  
            /// </summary>  
            /// <param name="control">Control to iterate</param>  
            /// <returns></returns>  
            public static List<TextBox> TextBoxList(this Control control) => control.Descendants<TextBox>().ToList();  
            /// <summary>  
            /// Get all DataGridViews controls in a control  
            /// </summary>  
            /// <param name="control">Control to iterate</param>  
            /// <returns></returns>  
            public static List<DataGridView> DataGridViewList(this Control control) => control.Descendants<DataGridView>().ToList();  
            /// <summary>  
            /// Get all ListViews in a control  
            /// </summary>  
            /// <param name="control">Control to iterate</param>  
            /// <returns></returns>  
            public static List<ListView> ListViewViewList(this Control control) => control.Descendants<ListView>().ToList();  
            /// <summary>  
            /// Get all CheckBoxes in a control  
            /// </summary>  
            /// <param name="control">Control to iterate</param>  
            /// <returns></returns>  
            public static List<CheckBox> CheckBoxList(this Control control) => control.Descendants<CheckBox>().ToList();  
            /// <summary>  
            /// Get all ComboBoxes in a control  
            /// </summary>  
            /// <param name="control">Control to iterate</param>  
            /// <returns></returns>  
            public static List<ComboBox> ComboBoxList(this Control control) => control.Descendants<ComboBox>().ToList();  
            /// <summary>  
            /// Get all ListBoxes in a control  
            /// </summary>  
            /// <param name="control">Control to iterate</param>  
            /// <returns></returns>  
            public static List<ListBox> ListBoxList(this Control control) => control.Descendants<ListBox>().ToList();  
            /// <summary>  
            /// Get all DateTimePickers in a control  
            /// </summary>  
            /// <param name="control">Control to iterate</param>  
            /// <returns></returns>  
            public static List<DateTimePicker> DateTimePickerList(this Control control) => control.Descendants<DateTimePicker>().ToList();  
            /// <summary>  
            /// Get all PictureBoxes in a control  
            /// </summary>  
            /// <param name="control">Control to iterate</param>  
            /// <returns></returns>  
            public static List<PictureBox> PictureBoxList(this Control control) => control.Descendants<PictureBox>().ToList();  
            /// <summary>  
            /// Get all Panels in a control  
            /// </summary>  
            /// <param name="control">Control to iterate</param>  
            /// <returns></returns>  
            public static List<Panel> PanelList(this Control control) => control.Descendants<Panel>().ToList();  
            /// <summary>  
            /// Get all GroupBoxes in a control  
            /// </summary>  
            /// <param name="control">Control to iterate</param>  
            /// <returns></returns>  
            public static List<GroupBox> GroupBoxList(this Control control) => control.Descendants<GroupBox>().ToList();  
            /// <summary>  
            /// Get all Buttons in a control  
            /// </summary>  
            /// <param name="control">Control to iterate</param>  
            /// <returns></returns>  
            public static List<Button> ButtonList(this Control control) => control.Descendants<Button>().ToList();  
            /// <summary>  
            /// Get all NumericUpDown controls in a control  
            /// </summary>  
            /// <param name="control">Control to iterate</param>  
            /// <returns></returns>  
            public static List<NumericUpDown> NumericUpDownList(this Control control) => control.Descendants<NumericUpDown>().ToList();  
            /// <summary>  
            /// Get checked CheckBox if any from a control/container  
            /// </summary>  
            /// <param name="control">Control to iterate</param>  
            /// <param name="pChecked">true or false</param>  
            /// <returns></returns>  
            public static RadioButton RadioButtonChecked(this Control control, bool pChecked = true) =>  
                control.Descendants<RadioButton>().ToList()  
                    .FirstOrDefault((radioButton) => radioButton.Checked == pChecked);  
      
            /// <summary>  
            /// Get a list of RadioButtons   
            /// </summary>  
            /// <param name="control">Control to iterate for RadioButtons</param>  
            /// <returns></returns>  
            public static List<RadioButton> RadioButtonList(this Control control) => control.Descendants<RadioButton>().ToList();  
            /// <summary>  
            /// Get control names for container e.g. a form, a GroupBox etc.  
            /// </summary>  
            /// <param name="controls">Control to iterate</param>  
            /// <returns></returns>  
            public static string[] ControlNames(this IEnumerable<Control> controls) => controls.Select((control) => control.Name).ToArray();  
        }  
      
    }  
    
    
      
    

1 additional answer

Sort by: Most helpful
  1. Viorel 111.7K Reputation points
    2020-12-17T10:58:55.617+00:00

    Make sure that the focusable controls have the corresponding TabStop=True and TabIndex properties.

    Then handle the Load event of the form:

    private void Form1_Load( object sender, EventArgs e )
    {
        var b = new Button { TabStop = false, Left = -1000 };
    
        b.Click += ( s, a ) =>
        {
            SelectNextControl( ActiveControl, true, true, true, true );
    
            switch( ActiveControl )
            {
            case TextBox tb:
                tb.SelectAll( );
                break;
            }
        };
    
        Controls.Add( b );
        AcceptButton = b;
    }
    

    Maybe adjust the switch for some other controls.