51

I need to make datagridview that only accept the numeric value for specific column only in keypress event. Is there any best way to do this?

Eplzong
  • 670
  • 1
  • 8
  • 13

7 Answers7

79
  • Add an event of EditingControlShowing
  • In EditingControlShowing, check that if the current cell lies in the desired column.
  • Register a new event of KeyPress in EditingControlShowing(if above condition is true).
  • Remove any KeyPress event added previously in EditingControlShowing.
  • In KeyPress event, check that if key is not digit then cancel the input.

Example:

private void dataGridView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
{
    e.Control.KeyPress -= new KeyPressEventHandler(Column1_KeyPress);
    if (dataGridView1.CurrentCell.ColumnIndex == 0) //Desired Column
    {
        TextBox tb = e.Control as TextBox;
        if (tb != null)
        {
            tb.KeyPress += new KeyPressEventHandler(Column1_KeyPress);
        }
    }
}

private void Column1_KeyPress(object sender, KeyPressEventArgs e)
{
    if (!char.IsControl(e.KeyChar) && !char.IsDigit(e.KeyChar))
    {
        e.Handled = true;
    }
}
  • 3
    I'm not criticizing this answer, but stating a general remark: Wouldn't it be nice to be able to set a formatter of some kind on a column with default formatters like `AllowNumericOnly` or so. Just like a property. – Mike de Klerk Oct 11 '13 at 10:30
  • 8
    Excellent answer! This keeps them from so much as typing invalid data. I would like to add though, that using a hard coded column index isn't a great idea. I would recommend using `if( dataGridView1.CurrentCell.ColumnIndex == dataGridView1.Columns["name"].Index )` – Drew Chapin Jul 23 '15 at 18:33
  • @druciferre Even better: `dataGridView1.CurrentCell.ColumnIndex == dataGridView.Columns.IndexOf(dataGridViewColumn1);` – Pontus Magnusson Oct 03 '16 at 08:40
  • 1
    @PontusMagnusson, couldn't you just use `dataGridViewColumn1.ColumnIndex` if you've defined a control for the column? – Drew Chapin Oct 03 '16 at 09:24
  • Wow who knew? Although it's `dgvc1.Index` – Pontus Magnusson Oct 03 '16 at 09:50
  • is this event in asp.net?I'm not able to add EditingControlShowing. – Sribin Dec 19 '17 at 04:54
  • WHAT IF I WANT NEGATIVE VALUES HERE. Just allowing '-' won't work because the user can place it anywhere for ex 123-23 – Anil Jul 18 '18 at 09:11
  • 2
    Good Answer, One thing to add here is that this does not prevent the user to paste from the context menu. – Huzaifa Nov 04 '20 at 17:55
  • Thanks for sharing this solution! That helped me! – Leandro Bresolin May 04 '21 at 17:03
36

You must use DataGridView.CellValidating Event like this :

    private void dataGridView1_CellValidating(object sender, 
                                           DataGridViewCellValidatingEventArgs e)
    {
        if (e.ColumnIndex == 1) // 1 should be your column index
        {
            int i;

            if (!int.TryParse(Convert.ToString(e.FormattedValue), out i))
            {
                e.Cancel = true;
                label1.Text ="please enter numeric";
            }
            else
            {
                // the input is numeric 
            }
        }
    }
Hamed
  • 2,084
  • 6
  • 22
  • 42
10
 private void dataGridView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
    {
        e.Control.KeyPress -= new KeyPressEventHandler(Column1_KeyPress);
        if (dataGridView1.CurrentCell.ColumnIndex == 4) //Desired Column
        {
            TextBox tb = e.Control as TextBox;
            if (tb != null)
            {
                tb.KeyPress += new KeyPressEventHandler(Column1_KeyPress);
            }
        }

    }
    private void Column1_KeyPress(object sender, KeyPressEventArgs e)
    { 
          // allowed only numeric value  ex.10
        //if (!char.IsControl(e.KeyChar)
        //    && !char.IsDigit(e.KeyChar))
        //{
        //    e.Handled = true;
        //}

               // allowed numeric and one dot  ex. 10.23
        if (!char.IsControl(e.KeyChar)&& !char.IsDigit(e.KeyChar)
             && e.KeyChar != '.')
        {
            e.Handled = true;
        }

        // only allow one decimal point
        if (e.KeyChar == '.'
            && (sender as TextBox).Text.IndexOf('.') > -1)
        {
            e.Handled = true;
        }
    }
Baby Groot
  • 4,637
  • 39
  • 52
  • 71
saurabh agrawal
  • 111
  • 1
  • 2
4

The answer given is excellent unless you require decimal places as others have pointed out. In this event you need to extend the validation, add the using and vars below to get a culture variable value for the decimal separator

using System.Globalization;

NumberFormatInfo nfi = Thread.CurrentThread.CurrentCulture.NumberFormat;
char decSeperator;

decSeperator = nfi.CurrencyDecimalSeparator[0];

Extend the validation to:

if (!char.IsControl(e.KeyChar) && !(char.IsDigit(e.KeyChar) 
| e.KeyChar == decSeperator))
{
    e.Handled = true;
}
// only allow one decimal point
if (e.KeyChar == decSeperator
    && (sender as TextBox).Text.IndexOf(decSeperator) > -1)
{
    e.Handled = true;
}
Rupert
  • 169
  • 1
  • 2
  • 4
  • 1
    I like the extended validation. I noticed though that a decimal character was never accepted as a valid KeyChar because the KeyPressEventArgs returned true even on entering the first decimal in the textbox. I added `else if (e.KeyChar == decSeparator) { e.Handled = false; }` as part of the IndexOf condition. Thanks – voidmain Nov 11 '15 at 19:06
  • Object reference not set to an instance of an object. – Tushar Narang Oct 04 '16 at 06:20
3
Private WithEvents txtNumeric As New DataGridViewTextBoxEditingControl

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

txtNumeric = CType(e.Control, DataGridViewTextBoxEditingControl)
End Sub

Private Sub txtNumeric_KeyPress(sender As Object, e As KeyPressEventArgs) Handles txtNumeric.KeyPress
    If (DataGridView1.CurrentCell.ColumnIndex > 0) Then
        If (Not Char.IsControl(e.KeyChar) And Not Char.IsDigit(e.KeyChar) And Not e.KeyChar = ".") Then
            e.Handled = True
        Else
            'only allow one decimal point
            If (e.KeyChar = "." And txtNumeric.Text.Contains(".")) Then
                e.Handled = True
            End If
        End If
    End If
End Sub
Bhavin Bhadani
  • 22,224
  • 10
  • 78
  • 108
0

You could also try this way, with accept decimals character

    private void Column1_KeyPress(object sender, KeyPressEventArgs e) 
    {
        //allow number, backspace and dot
        if (!(char.IsDigit(e.KeyChar) || e.KeyChar == (char)Keys.Back || e.KeyChar == '.'))
        {
            e.Handled = true;

        }
        //allow only one dot
        if (e.KeyChar == '.' && (sender as TextBox).Text.Contains("."))
        {
            e.Handled = true;

        }
    }
Ramgy Borja
  • 2,330
  • 2
  • 19
  • 40
0

I was doing a matrix calculator and was using two DataGridView objects. Here's a code that worked for me. I took the very first comment from this post and changed it a bit.

//Adding characters to a cell
    private void dataGridView_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
    {
        
            if (e.Control != null)
            {
                e.Control.KeyPress += new KeyPressEventHandler(Column1_KeyPress);
                Console.WriteLine(e.Control.Text);
            }
    }
    //Handling presses for minus dot and numbers
    private void Column1_KeyPress(object sender, KeyPressEventArgs e)
    {
        if (!char.IsControl(e.KeyChar) && !char.IsDigit(e.KeyChar) && e.KeyChar != '-' && e.KeyChar != '.')
            e.Handled = true;
        if (e.KeyChar == '.')
        {
            if (((DataGridViewTextBoxEditingControl)sender).Text.Length == 0)
                e.Handled = true;
            if (((DataGridViewTextBoxEditingControl)sender).Text.Contains('.'))
                e.Handled = true;
        }
        if (e.KeyChar == '-')
        {
            if (((DataGridViewTextBoxEditingControl)sender).Text.Length != 0)
                e.Handled = true;
            if (((DataGridViewTextBoxEditingControl)sender).Text.Contains('-'))
                e.Handled = true;
        }
    }