Search code examples
c#winformsdatagridviewuser-controlsdatagridviewtextboxcell

Handling keyboard events for custom DataGridView column type


In the code below I'm extending the class DataGridViewTextBoxCell to control the values that the user will input in this field, for that I need to catch the event KeyDown. But the event is invoked only when I'm navigating in the DGV using the keyboard. When I'm editing the value of the cell the event doesn't happen. What is missing in my code?

    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            DataGridView dataGridView = new DataGridView();

            MyDataGridViewColumn col = new MyDataGridViewColumn();
            dataGridView.Columns.Add(col);
            dataGridView.Rows.Add(new string[] { "0" });
            dataGridView.Rows.Add(new string[] { "1" });
            dataGridView.Rows.Add(new string[] { "2" });
            dataGridView.Rows.Add(new string[] { "3" });

            this.panel1.Controls.Add(dataGridView);
        }
    }

    public class MyDataGridViewColumn : DataGridViewColumn
    {
        public MyDataGridViewColumn()
        {
            this.CellTemplate = new MyDataGridViewTextBoxCell();
        }
    }

    public class MyDataGridViewTextBoxCell : DataGridViewTextBoxCell
    {
        protected override void OnKeyDown(KeyEventArgs e, int rowIndex)
        {
            base.OnKeyDown(e, rowIndex);

            var key = e.KeyCode;
        }
    }


Solution

  • Those key strokes will be handled by the editing control. If you want to create your own custom column type for this purpose, then you can to do it like this:

    1. Create your editing control by deriving from DataGridViewTextBoxEditingControl. Then override OnKeyDown and add your logic there.
    2. Create your cell by deriving from MyDataGridViewTextBoxCell. Then override EditType and return type of the editing control which you created in previous step.
    3. Finally, create your column by deriving from DataGridViewTextBoxColumn and in the constructor, set an instance of the cell that you created in the previous step, as its CellTemplate.

    Example

    public class MyDataGridViewTextBoxColumn : DataGridViewTextBoxColumn
    {
        public MyDataGridViewTextBoxColumn()
        {
            CellTemplate = new MyDataGridCViewTextBoxCell();
        }
    }
    public class MyDataGridCViewTextBoxCell : DataGridViewTextBoxCell
    {
        public override Type EditType => typeof(MyDataGridViewTextBoxEditingControl);
    }
    public class MyDataGridViewTextBoxEditingControl : DataGridViewTextBoxEditingControl
    {
        protected override void OnKeyDown(KeyEventArgs e)
        {
            base.OnKeyDown(e);
            //Put the logic here
        }
    }
    

    Note 1: For cases that you don't need to create a new column type, you can easily handle EditingControlShowing event of the DataGridView and check if the event belongs to your desired column, then get the editing control (and cast it to the right type), and then handle the proper event of the editing control, for example you can take a look at first code block in this example.

    Note 2: If you are interested to add custom properties to the column/cell and use them in the editing control, you can find a step by step answer including the sample code in this post: