C# – Let only some chars be typed in a datagridview cell

.netc++datagridviewvb.netwinforms

Is there a way to let only certain chars be added to a datagridview cell?
like '1234567890'?

Best Solution

There are two approaches I know of that you can use for this. The first (and I think the best) is to use the CellValidating event on the DataGridView and check if the entered text is numeric.

Here is an example of that which sets the row error value too (with an additional CellEndEdit event handler incase the user cancels out of editing).

private void dataGridView1_CellValidating(object sender,
        DataGridViewCellValidatingEventArgs e)
    {
        string headerText = 
            dataGridView1.Columns[e.ColumnIndex].HeaderText;

        // Abort validation if cell is not in the Age column.
        if (!headerText.Equals("Age")) return;

        int output;

        // Confirm that the cell is an integer.
        if (!int.TryParse(e.FormattedValue.ToString(), out output))
        {
            dataGridView1.Rows[e.RowIndex].ErrorText =
                "Age must be numeric";
            e.Cancel = true;
        }

    }

    void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e)
    {
        // Clear the row error in case the user presses ESC.   
        dataGridView1.Rows[e.RowIndex].ErrorText = String.Empty;
    }

The second approach is to use the EditingControlShowing event and the attach an event to the cell's KeyPress - I'm not such a fan of this approach since it silently blocks the input of non numeric keys - though I suppose you could give some feedback (like a bell sounding) it just feels like more work compared to the other way.

private void dataGridView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
{
    e.Control.KeyPress -= TextboxNumeric_KeyPress;
    if ((int)(((System.Windows.Forms.DataGridView)(sender)).CurrentCell.ColumnIndex) == 1)
    {
         e.Control.KeyPress += TextboxNumeric_KeyPress;
    }
}

private void TextboxNumeric_KeyPress(object sender, KeyPressEventArgs e)
{
    bool nonNumberEntered = true;

    if ((e.KeyChar >= 48 && e.KeyChar <= 57) || e.KeyChar == 8)
    {
        nonNumberEntered = false;
    }

    if (nonNumberEntered)
     {
        // Stop the character from being entered into the control since it is non-numerical.
        e.Handled = true;
    }
    else
    {
        e.Handled = false;
    }
}

One important note with this is be careful to remove the event handler on the control within the editing control showing method. This is important since the DataGridView reuses the same object for each cell of the same type, including across different columns. If you attach an event handler to a control in one textbox column, all the other text box cells in the grid will have the same handler! Also, multiple handlers will be attached, one for each time the control is shown.

The first solution came from this MSDN article. The second came from this blog.