Wednesday, December 8, 2010

DataGridView cell KeyPress event handler

DataGridView doesn’t provide an event for cell key actions like CellKeyPress, or CellKeyDown, etc for us to capture. The reason is that there’re several kinds of cells including DataGridViewTextBoxCell, DataGridViewComboBoxCell, DataGridViewCheckBoxCell and so on, and not all of those cell types, however, has KeyPress event.
However, there are 2 simple ways to get around this issue to catch cell KeyPress event.
The two example below showing how to limit key pressed to digits
1. Catch EditingControlShowCating event of DataGridView

private void gridData_EditingControlShowing(object sender,    
DataGridViewEditingControlShowingEventArgs e)
       {
           txtBox = e.Control as TextBox;
           if (txtBox != null)
               txtBox.KeyPress += txtBox_KeyPress;
 }

       private void txtBox_KeyPress(object sender, KeyPressEventArgs e)
       {
           if (!char.IsDigit(e.KeyChar) && e.KeyChar != (char)Keys.Back)
               e.Handled = true;
       }
    // detach the event from the current cell when it loses focus otherwise txtBox_KeyPress will launch mutiple times
       private void gridData_CellLeave(object sender, DataGridViewCellEventArgs e)
       {
           if (txtBox != null)
               txtBox.KeyPress -= txtBox_KeyPress;
}

2. Create a derived control from DataGridView and override ProcessDialogKey method:
Sample code: 
public partial class MyGrid : DataGridView 

{
private List<Keys> allowedKeys = new List<Keys> {Keys.D0, Keys.D1, Keys.D2, Keys.D3, 
Keys.D4,Keys.D5, Keys.D6, Keys.D7, Keys.D8, Keys.D9};

       public MyGrid()
           : base()
       {
           InitializeComponent();
       }

       protected override bool ProcessDialogKey(Keys keyData)
       {
           bool result = base.ProcessDialogKey(keyData);
           if (allowedKeys.Contains(keyData) == false)
               result = true;
           return result;
       }
    }