none
DataGridView, how to capture a cell's KeyPress event... RRS feed

  • Question

  • Hello all,

      I am trying to implement an event handler for the KeyPress event for
    a cell within a DataGridView control. The obvous starting point from
    the DataGridView keypress event, but this doesn't work for the cell. I
    found this posting while searching, but this doesn't work with the .NET
    2.0 beta framework.

    http://www.csharphelp.com/boar d2/read.html?f=1&i=35363&t=305 32

      I was trying to attempting something with the following...

    PropertyDescriptorCollection pcol =
    this.BindingContext[dtCanRegisters].GetItemProperties();

    Then assign the DataGridTableStyel to the properties, but I can't get
    it to work. Any ideas or suggestions? I am using VS.NET 2005 Express
    beta...

    Mark
    Tuesday, August 9, 2005 7:55 PM

Answers

  • Key press events when you are editing content in a cell does not come through the DataGridView's KeyPress event. You will need to either handle the KeyPress event directly on the editing control (you can get the editing control in the EditingControlShowing event). Alternatively you can derive from the DataGridView and override the ProcessDialogKey method which will get called for key events on the editing control.

    Hope this helps,
    -mark
    DataGridView Program Manager
    Microsoft
    This post is provided "as-is"

    Monday, August 22, 2005 5:24 PM

All replies

  • Key press events when you are editing content in a cell does not come through the DataGridView's KeyPress event. You will need to either handle the KeyPress event directly on the editing control (you can get the editing control in the EditingControlShowing event). Alternatively you can derive from the DataGridView and override the ProcessDialogKey method which will get called for key events on the editing control.

    Hope this helps,
    -mark
    DataGridView Program Manager
    Microsoft
    This post is provided "as-is"

    Monday, August 22, 2005 5:24 PM
  • Could you give some more details??
    Monday, October 23, 2006 8:22 PM
  • Hello Mark,

    I have the save problem. Could you give me a short sample for getting the EditingControlShowingEvent?

    Thanks in advance,

    Hardy

     

    Monday, January 8, 2007 4:59 PM
  • I have the same problem and I solve it like this:

    private void MyDataGridViewInitializationMethod()
    {
        ...
        dataGridView.EditingControlShowing +=
    new DataGridViewEditingControlShowingEventHandler(dataGridView_EditingControlShowing);
    }

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

    private void Control_KeyPress(object sender, KeyPressEventArgs e)
    {
        if (char.IsNumber(e.KeyChar))
        {
           //your code here
        }
    }

    et ça marche!!!
    Wednesday, May 23, 2007 8:47 PM
  • I found (accidently) that if the cells are read only, then they keypress event will fire.

     

    I could then use CurrentCell to manipulate the incoming text.

     

    One problem of course, is that you have to manually concat in each character and handle backspaces and things,

    as it will not be entered automatically due to the cell being read-only. 

     

     

    Wednesday, August 1, 2007 5:56 PM
  • Hi Shane,

    Thank You; good idea, but meanwhile we used Rakouns code, modified it to vb.net and found a solution like this:

     

    Private Sub CheckCell (ByVal sender As System.Object, ByVal e As System.Windows.Forms.KeyPressEventArgs)

    Dim KeyAscii As Short = Asc(e.KeyChar)

    '... 

    '... code to check the input

    '... 

    If KeyAscii = 0 Then

    e.Handled = True

    End If

    End Sub

     

    ' pass control to the keyPress-Event of active cell

    Private Sub DataGridView_EditingControlShowing(ByVal sender As Object, ByVal e As DataGridViewEditingControlShowingEventArgs) Handles DataGridView.EditingControlShowing

    Try

    '...to us this is a criteria, to only find and check "numeric" cells

    If e.CellStyle.Alignment = DataGridViewContentAlignment.MiddleRight Then

    AddHandler e.Control.KeyPress, AddressOf CheckCell

    Else

    'in order to prevent "optical problems", we had to call the removeHandler twice

    RemoveHandler e.Control.KeyPress, AddressOf CheckCell

    RemoveHandler e.Control.KeyPress, AddressOf CheckCell

    End If

     

    Catch ex As Exception

    '... 

    End Try

    End Sub

     

     

     

    Thursday, August 2, 2007 7:56 AM
  • Hello,

       Just got the same problem and used your solution. Worked perfectly!

    Thank you very much!
    Keren
    Monday, September 15, 2008 8:10 AM
  • hello,

     

    i had the same problem and used your solution. worked great!!

     

    thanks you very much!

    Jai

     

    Monday, September 15, 2008 9:14 AM
  • I am not really happy to call removehandler only twice; then is some cases did I had it more times.

     

    I prefer the way to store written text in a modulewidth variable and to remove handler according to variable length before I assign it again. Using of variable has the affect that I can format values in datagridview during input and can give a formatted value back to cell.

     

    Private Sub DataGridView_EditingControlShowing(ByVal sender As Object, ByVal e As DataGridViewEditingControlShowingEventArgs) Handles DataGridView.EditingControlShowing

    ...

    For i As Integer = 0 To Len(mstrInput)-1

    RemoveHandler e.Control.KeyPress, AddressOf CheckCell

    Next

    ...

    End Sub

     

     

    Private Sub CheckCell (ByVal sender As System.Object, ByVal e As System.Windows.Forms.KeyPressEventArgs)

    .....

    'fills the variable

    mstrInput += e.KeyChar

    ....

    End Sub
    • Proposed as answer by M3rcur14L Sunday, March 25, 2018 11:47 PM
    • Unproposed as answer by M3rcur14L Sunday, March 25, 2018 11:48 PM
    Monday, September 22, 2008 4:51 PM
  • This is very similar to LeyDaniel's, but I've just changed the loop to a boolean for speed:


    private bool eventHookedUp;  
     
    private void grdMyGrid_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)  
    {  
        //I just want to pick up on changes to column 2  
        if (this.grdMyGrid.CurrentCell.ColumnIndex == 2)  
        {  
            if (!this.eventHookedUp)  
            {  
                e.Control.KeyDown += this.Cell_KeyDown;  
                this.eventHookedUp = true;  
            }  
        }  
        else 
        {  
            e.Control.KeyDown -= this.Cell_KeyDown;
            this.eventHookedUp = false;
        }
    }
    private void Cell_KeyDown(object sender, KeyEventArgs e)  
    {  
       //Your code  
    }

    Monday, January 19, 2009 11:41 AM
  • I did one like Paul's, but moved the module-level variable to a local static variable. Also, I was already handling the KeyPress for the read-only columns, so I just hooked the event up to the existing KeyPress handler for the DGV, which consolidated things nicely (notwithstanding the whole EditingControlShowing rigamarole...)

        Private Sub dgvItems_KeyPress(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) Handles dgvItems.KeyPress
            'keypress will only fire when the cell is read-only
            If Char.IsLetterOrDigit(e.KeyChar) Then
                e.Handled = ShowItemSearch(dgvItems.CurrentCell.ColumnIndex, dgvItems.CurrentCell.RowIndex, e.KeyChar)
            End If
        End Sub
    
        Private Sub dgvItems_EditingControlShowing(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewEditingControlShowingEventArgs) Handles dgvItems.EditingControlShowing
            'keypress will only fire when the selected cell is read-only, so for the read/write column we do this to handle the KeyPress event
            Static bEventHookedUp As Boolean
            If dgvItems.CurrentCell.OwningRow.IsNewRow AndAlso dgvItems.CurrentCell.ColumnIndex = 1 Then
                If Not bEventHookedUp Then
                    AddHandler e.Control.KeyPress, AddressOf dgvItems_KeyPress
                    bEventHookedUp = True
                End If
            Else
                RemoveHandler e.Control.KeyPress, AddressOf dgvItems_KeyPress
                bEventHookedUp = False
            End If
        End Sub

    • Proposed as answer by M3rcur14L Sunday, March 25, 2018 11:49 PM
    • Unproposed as answer by M3rcur14L Sunday, March 25, 2018 11:49 PM
    • Proposed as answer by M3rcur14L Sunday, March 25, 2018 11:49 PM
    • Unproposed as answer by M3rcur14L Sunday, March 25, 2018 11:49 PM
    Sunday, May 3, 2009 1:21 AM
  • This works great, but I have one problem. I have two DataGridView controls on my form, and trying to capture KeyPress event for both of them. When I try to do it using this code, it seems that there is some conflict, and this code stops working.

    Any solution?

    Tnx in advance
    Tuesday, May 5, 2009 11:28 AM
  • I think you are going to more trouble than is necessary to get the datagridview keypress to work for you.
    Set the DataGridView ReadOnly property to <true> so the keypress event will work. Then in the KeyPress Sub place the following code statement:

    VB 2008

    DataGridView1.CurrentCell.Value &= e.KeyChar.ToString

    This will write the data back to the cell you are working with so you can read it. Even though the data grid read only
    property is set to true data can be written to the cell, though not directly from the keyboard, so the above code takes care of
    that for you. Now all you need to do is process the key characters however you need.
    Friday, October 16, 2009 7:51 PM
  • Hello Hardy Herzog,

     

    Thanks for your below code for my help.

     

    Thanks & Best Regards

    Tuesday, September 21, 2010 11:34 AM
  • hi all,

    im having a problem on implementing an event handler for the KeyPress event for
    a cell within a DataGridView control. I am using VB 2010. I always receive this error - "Nested sub does not have a signature that is compatible with delegate 'Delegate Sub KeyPressEventHandler(sender As Object, e As System.Windows.Forms.KeyPressEventArgs)'."

    here is the code that i used. i hope you could help me.

        Private Sub dgvBudgetList_EditingControlShowing(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewEditingControlShowingEventArgs)          Handles dgvBudgetList.EditingControlShowing


            Dim txtCell As TextBox = CType(e.Control, TextBox)

            If (txtCell IsNot Nothing) Then
                RemoveHandler txtCell.KeyPress, _
                    New EventHandler(AddressOf txtcell_keypress)

                AddHandler txtCell.KeyPress, _
                    New EventHandler(AddressOf txtcell_keypress)
            End If

        End Sub
       
        Private Sub txtcell_keypress(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyPressEventArgs)
           
        End Sub




    Thursday, June 23, 2011 3:19 AM
  • muchas gracias llevaba 1 1//2 buscando como hacerlo 

    en verdd me ha servido de mucho

    Tuesday, June 28, 2011 6:16 PM
  • How would you handle the EventHandler in vb?  I have basically the same scenario.  But would I use the AddressOf in VB? 
    Tuesday, July 26, 2011 10:02 PM
  • If the datagrid view cell is in edit mode. We need to handle the KeyPress event directly on the editing control (you can get the editing control in the EditingControlShowing event). Thanks Mark for sharing this.

    Ashish B

    Wednesday, May 16, 2012 5:42 AM
  • You can do this

    Private Sub dataGridView1_EditingControlShowing(ByVal sender As Object, _
            ByVal e As DataGridViewEditingControlShowingEventArgs) _
            Handles DataGridView1.EditingControlShowing
            Dim txtEdit As TextBox = e.Control
            'remove any existing handler
            RemoveHandler txtEdit.KeyPress, AddressOf txtEdit_Keypress
            AddHandler txtEdit.KeyPress, AddressOf txtEdit_Keypress
        End Sub
        Private Sub txtEdit_Keypress(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyPressEventArgs)
            Console.WriteLine("KeyPress " & e.KeyChar.ToString())
            'Test for numeric value or backspace in first column
            If DataGridView1.CurrentCell.ColumnIndex = 0 Then
                If IsNumeric(e.KeyChar.ToString()) _
                Or e.KeyChar = ChrW(Keys.Back) _
                Or e.KeyChar = "." Then
                    Console.WriteLine("KeyPress number")
                    e.Handled = False 'if numeric display 
                Else
                    Console.WriteLine("Enter Numbers Only")
                    e.Handled = True  'if non numeric don't display
                End If
            End If
        End Sub
    Hope this will helpful
    Monday, March 25, 2013 10:05 AM
  • Hello mark would you please tell me how to handle more than one control in EditingControlShowing event. Since i already added a handler for combobox column and i want to add hanler for textbox columns also.So user when moves to textbox cell i can restric them to enter only numeric values. Please help.
    Monday, March 25, 2013 10:21 AM
  • Don't Get too much into Handles else Handling will be difficult. Use DGV1.CurrentCell.R/Cindex values to manipulate. 

    I did same and am happy.

    Sunday, May 24, 2015 7:12 AM
  • In VB.net,

    e.control.keypress ------ not available..

    How to implement the above in VB.net?

    Need to get chars typed in datagridview cells..

    Thanks in advance.

    Kavitha.

    Monday, August 17, 2015 5:37 AM
  • in VB.net, e.KeyChar is not listed.
    Monday, August 17, 2015 6:54 AM
  • Agree with Shane. Make it ReadOnly

    More simple. Eg

     Private Sub Dgv1_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles Dgv1.KeyDown

            Dim i As Integer = Dgv1.CurrentCell.ColumnIndex
            Dim j As Integer = Dgv1.CurrentCell.RowIndex
            Dim s As String = Dgv1(i, j).Value
            Dim c As String = Chr(e.KeyValue)
                 s = Dgv1(i, j).Value
                 If e.KeyValue = 8 Then
                     If s <> "" Then Dgv1(i, j).Value = s.Substring(0, s.Length - 1)
                 Else
                    Dgv1(i, j).Value = Dgv1(i, j).Value & c
                 End If

    End Sub

     
    Thursday, October 1, 2015 11:47 PM
  • This may be a bit late but at least it's here for future searches

    create a contextmenustrip and name it "edit". in the contextmenustrip add a textbox and name it "EditTextBox", set size and font to your preferance

    then add this:-

    Private Sub Datagridview1_MouseUp(sender As Object, e As System.Windows.Forms.MouseEventArgs) Handles Datagridview1.MouseUp
        If e.Button = Windows.Forms.MouseButtons.Right Then
             Dim EndAddress As DataGridView.HitTestInfo = Datagridview1.HitTest(e.X, e.Y)
             EditTextBox.Text = Datagridview1.Rows(EndAddress.RowIndex).Cells(EndAddress.ColumnIndex).Value
        End If
    End Sub

    Private Sub EditTextBox_KeyDown(sender As Object, e As System.Windows.Forms.KeyEventArgs) Handles EditTextBox.KeyDown
        If e.KeyData = Keys.Return Then
             Datagridview1.Rows(EndRow).Cells(EndCol).Value = EditTextBox.Text
             'save changes to any database here
             Edit.Close()
        End If
    End Sub

    for me this seemed to be the most easiest way and easy to understand.


    Nicholas


    • Edited by NoZparker Wednesday, January 4, 2017 4:41 PM
    Wednesday, January 4, 2017 4:39 PM
  • I just needed to remove the handler once and then add the handler. It was not necessary to make it more than once.

    RemoveHandler e.Control.KeyPress, AddressOf dgv_page_dv_KeyPress
    AddHandler e.Control.KeyPress, AddressOf dgv_page_dv_KeyPress

    Sunday, March 25, 2018 11:51 PM