disable the default Enter/Return key behavior in a datagridview

40,296

Solution 1

You can try something like this in the gridview key down event

Private Sub DataGridView1_Keydown (...) Handles DataGridView1.KeyDown
   If e.KeyCode = Keys.Enter Then
       ' Your code here
       e.SuppressKeyPress = True
  End If 
End Sub

Another option would be to create a custom grid view control

DataGridView.ProcessDataGridViewKey Method

Solution 2

I myself, when disabling the Enter key’s default behavior on a DataGridView, want to be able to achieve a similar effect to setting DataGridView.StandardTab to true. Enabling StandardTab enables the user to more easily navigate between different controls in a form. This makes it behave more like a ListBox, especially if the DataGridView only has one column. The default behavior of of the Enter key and the behavior which I would expect from setting a (nonexistent) DataGridView.StandardEnter key to true would be to send the key event to containing controls, probably resulting in the Form.AcceptButton being activated. The proposed methods of setting KeyEventArgs.SuppressKeyPress = true in DataGridView.KeyDown or not even firing DataGridView.KeyDown when the input key is Enter do not enable “standard” Enter key behavior; these methods instead let the Enter key event get swallowed.

The following shows how I have managed to get “Standard” Enter key behavior (including invoking AcceptButton appropriately) out of a DataGridView. It is ugly because I do not know a better way to run the logic in Control.ProcessDialogKey() (which is just to call the Parent (the container)’s ProcessDialogKey() or return false if there is no Parent) than to copy it into my own derived class. (I essentially need to use the invalid/impossible base.base.ProcessDialogKey() syntax to work around System.Windows.Forms’s non-extensibility in a cleaner manner). Because of this, I am forced to use reflection to access the protected Control.ProcessDialogKey() method of the parent (the container) Control object when it exists.

DataGridVew.IsInputKey() returns true for Keys.Enter. This enables it to see the Enter key in its DataGridView.OnKeyDown() method where it eventually calls DataGridView.ProcessEnterKey() which reacts to the Enter key in different ways based on the setting of DataGridView.EditMode. But this also disables sending the key event to ProcessDialogKey() from where normal controls would bubble the Enter key event to their Parents (enabling AcceptButton to work, for example). Thus, we revert this behavior by overriding IsInputKey() and now DataGridView.ProcessDialogKey() will get called when Enter is pressed.

But that is not enough. DataGridView.ProcessDialogKey() has a hardcoded call to DataGridView.ProcessEnterKey() and only calls its base Control.ProcessDialogKey() if ProcessEnterKey() returns false. At this point, it would seem common sense to override ProcessEnterKey() with something that would just return false when we want standard Enter key behavior. But, alas, it is a non-virtual method. Thus, we are forced to override something we can override, DataGridView.ProcessDialogKey(), and reimplement it while skipping the call to ProcessEnterKey(). This is where we are also unable to directly call Control.ProcessDialogKey() and are forced to use reflection to call the parent/container object’s ProcessDialogKey() method. But once we successfully make that call, we finally have standard Enter behavior and AcceptButton is accessible even while the DataGridView has focus!

/// <summary>
///   A DataGridView with a StandardEnter property which behaves
///   like StandardTab.
/// </summary>
class StandardEnterDataGridView
: DataGridView
{
    /// <summary>
    ///   Like StandardTab but for the Enter key.
    /// </summary>
    [Category("Behavior"), Description("Disable default edit/advance to next row behavior of of the Enter key.")]
    public bool StandardEnter { get; set; }

    /// <summary>
    ///   Implement StandardEnter.
    /// </summary>
    protected override bool IsInputKey(Keys keyData)
    {
        if (StandardEnter && keyData == Keys.Enter)
            // Force this key to be treated like something to pass
            // to ProcessDialogKey() (like the Enter key normally
            // would be for controls which aren’t DataGridView).
            return false;

        return base.IsInputKey(keyData);
    }

    private static MethodInfo _Control_ProcessDialogKey = typeof(Control).GetMethod("ProcessDialogKey", BindingFlags.Instance|BindingFlags.NonPublic);

    protected override bool ProcessDialogKey(Keys keyData)
    {
        if (StandardEnter && keyData == Keys.Enter)
            // Copy the default implementation of
            // Control.ProcessDialogKey(). Since we can’t access
            // the base class (DataGridView)’s base class’s
            // implementation directly, and since we cannot
            // legally access Control.ProcessDialogKey() on other
            // Control object, we are forced to use reflection.
            return Parent == null ? false : (bool)_Control_ProcessDialogKey.Invoke(Parent, new object[] {keyData, });

        return base.ProcessDialogKey(keyData);
    }
}

Solution 3

You can just use keyPress event:

 private void dataGridView1_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter)
            {
                //You're Code
            }
            e.Handled = true;
            return;
        }

Solution 4

Override the DataGridView (write your own that inherits from it), and process the OnKeyDown method.

public partial class UserControl1 : DataGridView
{
    public UserControl1()
    {
        InitializeComponent();
    }

    protected override void OnKeyDown(KeyEventArgs e)
    {
        if (e.KeyCode == Keys.Enter)
            return;

        base.OnKeyDown(e);
    }
}

Solution 5

I am adding this foot note to this as I was very interested in this article since it ran close to a different problem I had with the DataGridView. This is that the fact the Enter key takes you to the cell below, preventing a users ability to do simple editing to text in a cell. Having overridden the class and spent much time on this, I finally found the following article: Use Enter to add new line in datagridview cell

If this is your only issue, then to know SHIFT+ENTER works (however unintuitive), might save you a lot of time! Think I will just add a label to the form to remind users.

Share:
40,296
Ramji
Author by

Ramji

A Simple Guy

Updated on July 09, 2022

Comments

  • Ramji
    Ramji almost 2 years

    In vb.net datagridview the default Enter/Return key behavior is to move to the next row is there a quick and easy way to avoid that.

    Any suggestions are welcome

  • Viku
    Viku over 10 years
    Application terminates as soon as it comes to e.suppressKeyPress = true .
  • duardbr
    duardbr about 8 years
    I just change the declaration of my Gride to this new class but nothing happens, ENTER KEY still going to the next row :-/ this.dbGride = new StandardEnterDataGridView();
  • binki
    binki about 8 years
    @duardbr I haven’t looked at this code in a long time, but given that you wrote this.dbGride = new StandardEnterDataGridView(); in your comment, did you remember to set the StandardEnter property to true? Perhaps this.dbGride = new StandardEnterDataGridView { StandardEnter = true, };. Or if you’re using VS Designer try enabling the StandardEnter property in the Designer’s property grid view.
  • duardbr
    duardbr about 8 years
    Thanks for reply, yes, StandardEnter is True and nothing happens
  • Birk
    Birk about 7 years
    This worked like a charm. Simple but only solution of the proposed, which worked for me.
  • ourmandave
    ourmandave over 3 years
    KeyDown, not KeyPress. Scanning the code missed that. My tip off was there's no e.KeyCode in KeyPress.