How to prevent going to next row after editing a DataGridViewTextBoxColumn and pressing EnterKey?
Asked Answered
M

10

20

I'm working on a program with DataGridViews. In one DatagridView there is a DataGridViewTextBoxColumn, which is enabled to be edited by the user. When the user is done with typing the numbers into it, he presses ENTER on the keyboard. Now the DataGridView does all its Events, and after all Events, the last thing is the problem.

Everything is done, and Windows is going to Select the next DataGridViewRow, and I'm not able to prevent this.

I tried

if (e.KeyData == Keys.Enter) e.SuppressKeyPress = true; // or e.Handled 

in nearly every event I found. Sadly I was only able to Prevent the ENTER key when the DataGridViewTextBoxColumn is not in edit mode.

Heres my methode t find the ENTER while in Editing

Adding the Event

private void dgr_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
{
    e.Control.KeyPress += new KeyPressEventHandler(dgr_KeyPress_NumericTester);
}

And this is the event to accept numeric input only.

private void dgr_KeyPress_NumericTester(object sender, KeyPressEventArgs e)
{
    if (!Char.IsDigit(e.KeyChar) && e.KeyChar != 8) e.Handled = true;
}

To explain in detail:

When the user enters a Value, that has some dependings, I would like to give another control the focus, so he is used to correct the dependings.

I also tried it with DependingControl.Focus() but the last "enter" is going to be the last thing on the view.

Does someone know how to prevent this?

Mikiso answered 24/4, 2011 at 16:2 Comment(1)
You need only to override the ProcessCmdKey, see [here for how](windowsclient.net/blogs/faqs/archive/2006/05/30/… ) and [here for why][2] [2]: blogs.msdn.com/b/jfoscoding/archive/2005/01/24/359334.aspxDibbuk
P
8

Well, I managed to get something working that does what you want (or at least does the hard part, I think you have already done most of the other stuff) but the solution makes my skin crawl.

What I ended up with to "cancel" the enter key event when editing a cell as to use a mixture of the CellEndEdit event and the SelectionChanged event.

I introduced a couple of class level fields that store some state - in particular what row we are in at the end of editing a cell and whether we are stopping a selection changed.

The code looks like this:

public partial class Form1 : Form
{
    private int currentRow;
    private bool resetRow = false;

    public Form1()
    {
        InitializeComponent();

        // deleted out all the binding code of the grid to focus on the interesting stuff

        dataGridView1.CellEndEdit += new DataGridViewCellEventHandler(dataGridView1_CellEndEdit);

        // Use the DataBindingComplete event to attack the SelectionChanged, 
        // avoiding infinite loops and other nastiness.
        dataGridView1.DataBindingComplete += new DataGridViewBindingCompleteEventHandler(dataGridView1_DataBindingComplete);
    }

    void dataGridView1_SelectionChanged(object sender, EventArgs e)
    {
        if (resetRow)
        {
            resetRow = false;
            dataGridView1.CurrentCell = dataGridView1.Rows[currentRow].Cells[0];          
        }
    }

    void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e)
    {
        resetRow = true;
        currentRow = e.RowIndex;
    }

    void dataGridView1_DataBindingComplete(object sender, DataGridViewBindingCompleteEventArgs e)
    {
        dataGridView1.SelectionChanged += new EventHandler(dataGridView1_SelectionChanged);
    }
} 

You'll want to test this thoroughly to make sure it does exactly what you need. I only checked to see that it does stop a row change when pressing enter out of an editing control.

As I said - I'm not too happy with needing to do something like this - it feels quite brittle, and also like it could have weird side effects. But if you must have this behaviour, and you test it well I think this is the only way to do what you want.

Pipit answered 24/4, 2011 at 22:34 Comment(1)
This is working fine for me. Just one small bug when I'm trying to leave a DataGridViewCheckBoxCell i must not set resetRow, becourse it will jail my focus in the CheckBox. if (dataGridView1.CurrentCell is DataGridViewCheckBoxCell) resetRow = false; I was working with SelectedRow instead of changing the CurrentCell property, and this was not working well in my test... now its fine, thx a lot for this!Mikiso
O
11

I tried this for changing the Enter behaviour for your Grid by inheriting a customcolumn from Textbox column and overriding the below event

protected override bool ProcessDialogKey(Keys keyData)
{
    if (keyData == Keys.Enter)
       return base.ProcessDialogKey(Keys.Tab);
    else
       return base.ProcessDialogKey(keyData);
}

So instead of the Enter Key being sent it emulates the action for Tab which will move to the next cell. Hope this helps

Occidentalize answered 25/4, 2011 at 4:42 Comment(1)
Also a great way. Thanks for this too!Mikiso
P
8

Well, I managed to get something working that does what you want (or at least does the hard part, I think you have already done most of the other stuff) but the solution makes my skin crawl.

What I ended up with to "cancel" the enter key event when editing a cell as to use a mixture of the CellEndEdit event and the SelectionChanged event.

I introduced a couple of class level fields that store some state - in particular what row we are in at the end of editing a cell and whether we are stopping a selection changed.

The code looks like this:

public partial class Form1 : Form
{
    private int currentRow;
    private bool resetRow = false;

    public Form1()
    {
        InitializeComponent();

        // deleted out all the binding code of the grid to focus on the interesting stuff

        dataGridView1.CellEndEdit += new DataGridViewCellEventHandler(dataGridView1_CellEndEdit);

        // Use the DataBindingComplete event to attack the SelectionChanged, 
        // avoiding infinite loops and other nastiness.
        dataGridView1.DataBindingComplete += new DataGridViewBindingCompleteEventHandler(dataGridView1_DataBindingComplete);
    }

    void dataGridView1_SelectionChanged(object sender, EventArgs e)
    {
        if (resetRow)
        {
            resetRow = false;
            dataGridView1.CurrentCell = dataGridView1.Rows[currentRow].Cells[0];          
        }
    }

    void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e)
    {
        resetRow = true;
        currentRow = e.RowIndex;
    }

    void dataGridView1_DataBindingComplete(object sender, DataGridViewBindingCompleteEventArgs e)
    {
        dataGridView1.SelectionChanged += new EventHandler(dataGridView1_SelectionChanged);
    }
} 

You'll want to test this thoroughly to make sure it does exactly what you need. I only checked to see that it does stop a row change when pressing enter out of an editing control.

As I said - I'm not too happy with needing to do something like this - it feels quite brittle, and also like it could have weird side effects. But if you must have this behaviour, and you test it well I think this is the only way to do what you want.

Pipit answered 24/4, 2011 at 22:34 Comment(1)
This is working fine for me. Just one small bug when I'm trying to leave a DataGridViewCheckBoxCell i must not set resetRow, becourse it will jail my focus in the CheckBox. if (dataGridView1.CurrentCell is DataGridViewCheckBoxCell) resetRow = false; I was working with SelectedRow instead of changing the CurrentCell property, and this was not working well in my test... now its fine, thx a lot for this!Mikiso
K
7
Private Sub DataGridView1_KeyDown(sender As Object, e As KeyEventArgs) Handles DataGridView1.KeyDown
    If e.KeyData = Keys.Enter Then e.Handled = True
End Sub

It's just a workaround, not a real solution, but it works.

Keiko answered 9/7, 2015 at 14:48 Comment(1)
Simplest and does exactly what is needed.Learnt
R
2

You can do it simply....

1...Create the KeyDown Event for that grid view.(Go to properties on the gridview and double click the KeyDown event).

2...Past this code -

if(e.KeyData == Keys.Enter)
{
  e.Handled = true;
}

3...Finally its look like this.

private void dgvSearchResults_KeyDown(object sender, KeyEventArgs e)
{
  if (e.KeyData == Keys.Enter)
   {
    e.Handled = true;
   }
}

4..Run the program and see.

Ruvalcaba answered 21/3, 2015 at 20:14 Comment(0)
M
2

This answer really comes late...

But i had the exact same Problem and did not want to cache rows etc. So i googled around and this is my solution to the question. Credits to How to prevent an Enter key press from ending EditMode in a DataGridView?

Inherit from DataGridView and add this code (vb.net):

Protected Overrides Function ProcessCmdKey(ByRef msg As Message, keyData As Keys) As Boolean
    If Commons.Options.RowWiseNavigation AndAlso Me.IsCurrentCellInEditMode AndAlso (keyData = Keys.Enter Or keyData = Keys.Tab) Then
        ' End EditMode, then raise event, so the standard-handler can run and the refocus is being done
        Me.EndEdit()
        OnKeyDown(New KeyEventArgs(keyData))
        Return True
    End If

    'Default
    Return MyBase.ProcessCmdKey(msg, keyData)
End Function
Monicamonie answered 22/2, 2017 at 14:39 Comment(0)
C
1

I know that this question was asked since long time ago but the answer may be useful for those who search in future i hope so. the best solution is to use your custom column and for textbox its easy because we will take advantage of the built in classes

class Native
{
    public const uint WM_KEYDOWN = 0x100;
    [DllImport("user32.dll")]
    public static extern bool PostMessage(IntPtr hWnd, UInt32 Msg, Int32 wParam, Int32 lParam);
}
//the column that will be added to dgv
public class CustomTextBoxColumn : DataGridViewColumn
{
    public CustomTextBoxColumn() : base(new CustomTextCell()) { }
    public override DataGridViewCell CellTemplate
    {
        get { return base.CellTemplate; }
        set
        {
            if (value != null && !value.GetType().IsAssignableFrom(typeof(CustomTextCell)))
            {
                throw new InvalidCastException("Must be a CustomTextCell");
            }
            base.CellTemplate = value;
        }
    }
}
//the cell used in the previous column
public class CustomTextCell : DataGridViewTextBoxCell
{
    public override Type EditType
    {
        get { return typeof(CustomTextBoxEditingControl); }
    }
}
//the edit control that will take data from user
public class CustomTextBoxEditingControl : DataGridViewTextBoxEditingControl
{
    protected override void WndProc(ref Message m)
    {
        //we need to handle the keydown event
        if (m.Msg == Native.WM_KEYDOWN)
        {
            if((ModifierKeys&Keys.Shift)==0)//make sure that user isn't entering new line in case of warping is set to true
            {
                Keys key=(Keys)m.WParam;
                if (key == Keys.Enter)
                {
                    if (this.EditingControlDataGridView != null)
                    {
                        if(this.EditingControlDataGridView.IsHandleCreated)
                        {
                            //sent message to parent dvg
                            Native.PostMessage(this.EditingControlDataGridView.Handle, (uint)m.Msg, m.WParam.ToInt32(), m.LParam.ToInt32());
                            m.Result = IntPtr.Zero;
                        }
                        return;
                    }
                }
            }
        }
        base.WndProc(ref m);
    }
}

then we come to the dgv itself i used a new class derived from DataGridView and added my columns and handled the enter key from the wndproc also

void Initialize()
{
    CustomTextBoxColumn colText = new CustomTextBoxColumn();
    colText.DataPropertyName = colText.Name = columnTextName;
    colText.HeaderText = columnTextAlias;
    colText.DefaultCellStyle.WrapMode = DataGridViewTriState.True;
    this.Columns.Add(colText);
    DataGridViewTextBoxColumn colText2 = new DataGridViewTextBoxColumn();
    colText2.DataPropertyName = colText2.Name = columnText2Name;
    colText2.HeaderText = columnText2Alias;
    colText2.DefaultCellStyle.WrapMode = DataGridViewTriState.False;
    this.Columns.Add(colText2);
}
protected override void WndProc(ref Message m)
{
    //the enter key is sent by edit control
    if (m.Msg == Native.WM_KEYDOWN)
    {
        if ((ModifierKeys & Keys.Shift) == 0)
        {
            Keys key = (Keys)m.WParam;
            if (key == Keys.Enter)
            {
                MoveToNextCell();
                m.Result = IntPtr.Zero;
                return;
            }
        }
    }

    base.WndProc(ref m);
}

//move the focus to the next cell in same row or to the first cell in next row then begin editing
public void MoveToNextCell()
{
    int CurrentColumn, CurrentRow;
    CurrentColumn = this.CurrentCell.ColumnIndex;
    CurrentRow = this.CurrentCell.RowIndex;
    if (CurrentColumn == this.Columns.Count - 1 && CurrentRow != this.Rows.Count - 1)
    {
        this.CurrentCell = Rows[CurrentRow + 1].Cells[1];//0 index is for No and readonly
        this.BeginEdit(false);
    }
    else if(CurrentRow != this.Rows.Count - 1)
    {
        base.ProcessDataGridViewKey(new KeyEventArgs(Keys.Tab));
        this.BeginEdit(false);
    }
}
Coastline answered 28/3, 2012 at 23:39 Comment(0)
K
1

Simply Do that it will be working all right.

private void dataGridViewX1_CellEndEdit(object sender, DataGridViewCellEventArgs e)
    {

        SendKeys.Send("{UP}");
        SendKeys.Send("{Right}");
    }
Konstanze answered 5/11, 2016 at 5:55 Comment(0)
F
0

Based on this solution, I've created my own. You don't need to catch KeyDown_Event on the DataGrid for the Enter_key, but rather toggle the AllowUserToAddRows property. In my case, I opted for the CellContentDoubleClick for enabling it:

private void myDataGrid_CellBeginEdit(object sender, DataGridViewCellCancelEventArgs e) {
    myDataGrid.AllowUserToAddRows = false;
}

private void myDataGrid_CellContentDoubleClick(object sender, DataGridViewCellEventArgs e) {
    myDataGrid.AllowUserToAddRows = true;
}
Floruit answered 21/7, 2022 at 7:52 Comment(0)
S
0

The only way i found to do this was creating a custom DataGridView.

Edit: This change the default behavior of the arrow keys, and permit the use of the arrow keys in editing. You can change this removing "e.KeyCode == Keys.Left || e.KeyCode == Keys.Right".

    public class CustomDataGridview : DataGridView
    {
        protected override bool ProcessDataGridViewKey(KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter || e.KeyCode == Keys.Left || e.KeyCode == Keys.Right)
            {
                return false;
                //if (IsCurrentCellInEditMode)   // disable the keys only in EditMode
                //{
                //    return false;
                //}
            }
            return base.ProcessDataGridViewKey(e);
        }

        protected override bool ProcessDialogKey(Keys keyData)
        {
            if (keyData == Keys.Enter)
            {
                EndEdit();
                return true;
            }
            return base.ProcessDialogKey(keyData);
        }
    }

    CustomDataGridview dgvCustom = new CustomDataGridview();
    DataGridViewTextBoxColumn InputFile2 = new DataGridViewTextBoxColumn();
    DataGridViewTextBoxColumn OutputFile2 = new DataGridViewTextBoxColumn();
    DataGridViewComboBoxColumn Format2 = new DataGridViewComboBoxColumn();
    DataGridViewTextBoxColumn Options2 = new DataGridViewTextBoxColumn();

    private void SetupDataGridView()
    {
        //All your DataGridView settings
    }

    public Form1()
    {
        InitializeComponent();
        SetupDataGridView();
    }
Shirelyshirey answered 27/4, 2023 at 23:0 Comment(1)
As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.Mandi
B
-1

If you need to just close the form on enter, you can use following code. I suppose that the grid is readonly and you don't need to distinquish the situation in which the enter was pressed.

public class DataGridViewNoEnter : DataGridView
{       
    protected override bool ProcessDataGridViewKey(KeyEventArgs e)
    {
        if (e.KeyCode == Keys.Enter)
        {
            ((Form)this.TopLevelControl).DialogResult = DialogResult.OK;
            return false;
        }
        return base.ProcessDataGridViewKey(e);
    }      
}
Becky answered 17/9, 2014 at 7:40 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.