yonan2236
yonan2236

Reputation: 13659

How to handle KeyEvents in a DataGridViewCell?

Is there a Keydown Event of a DataGridViewCell?
What I'm trying to do is when a user is typing in a particular cell, he can press F1 for help of that particular column. And some Form will popup...

What event it is?

Upvotes: 11

Views: 52412

Answers (8)

Ruslan
Ruslan

Reputation: 1

to this answer:

In your solution you shouldn't forget to unlistern to the event

private void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e)
{
  tb.KeyUp -= Tb_KeyUp;
}

And in my solution i subscribed to KeyUp, not KeyDown, because i need to replace value of editing cell

DataGridViewTextBoxEditingControl tb { get; set; }

private void dataGridView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
{
    tb = (DataGridViewTextBoxEditingControl)e.Control;
    CellEditingTB.KeyUp += Tb_KeyUp;
}

private void Tb_KeyUp(object sender, KeyEventArgs e)
{
    if (tb != null)
    {
        if (e.KeyCode == Keys.Decimal)
        {
            ..
        }
    }
}

Upvotes: 0

user3732201
user3732201

Reputation: 31

overriding the virtual function ProcessCmdKey for class Form worked for me.

Return true on ProcessCmdKey to prevent further handling of the keypress. the overrided function to catches all of the key actions

Ex:

protected override bool ProcessCmdKey(ref Message msg, Keys keyData) //overridden virtual function
{
    if (keyData == Keys.Tab) //check to make sure it is the key I am interested in
    { 
        if (this.dataGridViewKeys.ContainsFocus) //make sure it is on the control, or any child controls, of the one I am interested in
        {
            this.dataGridViewKeys.EndEdit(); //do whatever action you want here
            if (this.dataGridViewKeys.CurrentRow.IsNewRow && this.dataGridViewKeys.Rows.Count > 1)
                this.dataGridViewKeys.CurrentCell = this.dataGridViewKeys.Rows[this.dataGridViewKeys.Rows.Count - 1].Cells[2];
            this.txtNoteData.Focus();
            return true;  //I return true to prevent further handling of the keypress
        }
    }
    return base.ProcessCmdKey(ref msg, keyData); //return this for keys you do not want to intercept
}

Upvotes: 0

yonan2236
yonan2236

Reputation: 13659

I found this code in a forum, and it works.

private void dataGridView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
{
   DataGridViewTextBoxEditingControl tb = (DataGridViewTextBoxEditingControl)e.Control;
   tb.KeyPress += new KeyPressEventHandler(dataGridViewTextBox_KeyPress);    
   e.Control.KeyPress += new KeyPressEventHandler(dataGridViewTextBox_KeyPress);
}
    
private void dataGridViewTextBox_KeyPress(object sender, KeyPressEventArgs e)
{
   //when i press enter,bellow code never run?
   if (e.KeyChar==(char)Keys.Enter)
   {
      MessageBox.Show("You press Enter");
   }
}

Upvotes: 25

SourceCenter
SourceCenter

Reputation: 1

This code did work for me.

Form.KeyPreview = true;

Description in Microsoft Docs: "...(KeyPreview) sets a value indicating whether the form will receive key events before the event is passed to the control that has focus.".

Upvotes: 0

Colin Steel
Colin Steel

Reputation: 1055

I know this is an old question, but I believe I have improved upon the top voted answer.

    IDataGridViewEditingControl _iDataGridViewEditingControl;
    private void SlotTimesDGV_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
    {
        if (_iDataGridViewEditingControl is DataGridViewComboBoxEditingControl)
        {
            DataGridViewComboBoxEditingControl iDataGridViewEditingControl = _iDataGridViewEditingControl as DataGridViewComboBoxEditingControl;
            iDataGridViewEditingControl.KeyPress -= SlotTimesDGV_EditingControlShowing_KeyPress;
        }
        if (e.Control is DataGridViewComboBoxEditingControl)
        {
            DataGridViewComboBoxEditingControl iDataGridViewEditingControl = e.Control as DataGridViewComboBoxEditingControl;
            iDataGridViewEditingControl.KeyPress += SlotTimesDGV_EditingControlShowing_KeyPress;
            _iDataGridViewEditingControl = iDataGridViewEditingControl;
        }
    }

    private void SlotTimesDGV_EditingControlShowing_KeyPress(object sender, KeyPressEventArgs e)
    {
        MessageBox.Show("");
    }

By having an instance variable of the IDataGridViewEditingControl, you can remove the KeyPress event that would result in duplicate calls when moving around cells and your event is not limited to only one type of cell.

Upvotes: 1

Federico Sanchez
Federico Sanchez

Reputation: 21

another solution is

private void grdDetalle_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
    {
        // Sólo queremos esta funcionalidad para determinadas columnas Clave y Nombre
        if ((grdDetalle.Columns[grdDetalle.CurrentCell.ColumnIndex].Name == "colClaveArticulo") ||
            (grdDetalle.Columns[grdDetalle.CurrentCell.ColumnIndex].Name == "colNombre"))
        {
            /// Workarround para que estando editando en las columnas del grid Clave y Nombre
            /// podamos detectar cuando se dio F4 para lanzar el dialogo de busqueda del
            /// articulo.
            e.Control.KeyDown += new KeyEventHandler(dataGridViewTextBox_KeyDown);
            e.Control.Leave += new EventHandler(dataGridViewTextBox_Leave);
        }
    }

    private void dataGridViewTextBox_Leave(object sender, EventArgs e)
    {

        if ((grdDetalle.Columns[grdDetalle.CurrentCell.ColumnIndex].Name == "colClaveArticulo") ||
           (grdDetalle.Columns[grdDetalle.CurrentCell.ColumnIndex].Name == "colNombre"))
        {
            try
            {
                (sender as DataGridViewTextBoxEditingControl).KeyDown -= 
                   new KeyEventHandler(dataGridViewTextBox_KeyDown);
            }
            catch (Exception ex)
            { }
        }
    }

    private void dataGridViewTextBox_KeyDown(object sender, KeyEventArgs e)
    {
        // F4 Pressed
        if ((grdDetalle.Columns[grdDetalle.CurrentCell.ColumnIndex].Name == "colClaveArticulo") ||
           (grdDetalle.Columns[grdDetalle.CurrentCell.ColumnIndex].Name == "colNombre"))
        {
            if (e.KeyCode == Keys.F4) // 115
            {
                MessageBox.Show("Oprimieron F4");
                e.Handled = true;
                e.SuppressKeyPress = true;
            }
        }
    }

Upvotes: 2

Phil Wright
Phil Wright

Reputation: 22956

When the user types into a cell it is actually typing into the control that is placed inside the cell for editing purposes. For example, a string column type will actually create a TextBox for use inside the cell for the user to input against. So you need to actually hook into the KeyDown event of the TextBox that is placed inside the cell when editing takes place.

Upvotes: 3

Timwi
Timwi

Reputation: 66604

DataGridViewCell doesn’t have any events, but you can listen for the KeyDown event on the DataGridView itself and then look at which cell is selected:

public void dataGridView_KeyDown(object sender, KeyEventArgs e)
{
    if (e.KeyCode == Keys.F1)
    {
        var selectedCell = dataGridView.SelectedCells[0];
        // do something with selectedCell...
    }
}

Upvotes: 6

Related Questions