Popping up a different edit control in .NET DataGridView

I’ve been working the past few days with changing behaviors of the DataGridView, where the displayed contents are formatted strings that are determined by conditionally-created combo boxes, checked list boxes, and prompts.  After a misguided attempt using CellEnter that resulted in numerous infinite loops, stack overflows, and “reentrant call to the SetCurrentCellAddressCore function” error messages, I found this solution by Mark Rideout, Microsoft’s DataGridView Program Manager, that overrides either CellBeginEdit or EditingControlShowing (I used CellBeginEdit).  He describes the drawback that the keystroke used to enter edit mode will not be sent to the control, and suggests deriving DataGridViewCell and overriding InitializeEditingControl and KeyEntersEditMode.  Here’s how I implemented it without deriving a separate class.

I overrode the form’s ProcessCmdKey function like this:

protected override bool ProcessCmdKey(ref System.Windows.Forms.Message msg, System.Windows.Forms.Keys keyData)
{
    // Get the value of the key that was pressed
    int KeyValue = msg.WParam.ToInt32();
    // See if the key is a letter or digit (i.e., something to pass to the next control
    if (Char.IsLetterOrDigit(((char)KeyValue)))
    {
        // Store the integer value of the last key press
        m_LastKeyPressed = KeyValue;
        // Store whether the datagrid had focus or not
        m_LastKeyPressDataGridHasFocus = dgLineItems.Focused;
        // Store the cell that is being typed into
        m_LastKeyPressCell = m_LastKeyPressDataGridHasFocus ? dgLineItems.CurrentCell : null;
    }
    // Allow normal processing of the keystroke
    return base.ProcessCmdKey(ref msg, keyData);
}

And the CellBeginEdit like this:

void MyDataGrid_CellBeginEdit(object sender, DataGridViewCellCancelEventArgs e)
{
    // See which column is being edited
    switch (dgLineItems.Columns[e.ColumnIndex].Name)
    {
        case "MyCustomEditControlColumn":
            // Don't let the DataGridViewCell be edited
            e.Cancel = true;
            /// TODO: Add code here to show custom control; either need to have the control update the underlying data or wait for it after sending the keypress
            // Replay the last keypress to the new control
            if (m_LastKeyPressCell == MyDataGrid.CurrentCell)
            {
                SendKeys.Send(((char)m_LastKeyPressed).ToString());
            }
            break;
    }
}

I don’t think it’s necessary to use the BeginInvoke anonymous delegate; using e.Cancel seemed to do the trick.

Advertisements

3 thoughts on “Popping up a different edit control in .NET DataGridView

  1. Hi,

    I need a usercontrol with a textbox and a button, within a datagridview cell, in edit mode, but I don’t know how. Some examples loss focus, or don’t run with the keyboard.
    Your code it’s good, but I don’t know if it is possible run with an usercontrol in the datagridview cell.
    Any ideas?
    Thanks

  2. Hi pserranop, I’m not sure about with a usercontrol, but I’ve used the same principle above to open a form and send the last pressed key to the form in its constructor. You could give that a try to see if you have any success with it.

    The other possibility is that if you’re using a non-US keyboard, Char.IsLetterOrDigit(((char)KeyValue))) may not return what you expect–you may want to use Console.WriteLine((char)KeyValue) to see what is actually being processed. I have a subsequent post dealing with getting the key pressed from the key message here:

    https://geeknotes.wordpress.com/2007/04/03/translating-systemwindowsformskeys-to-char-data-in-processcmdkey/

    that may help if that’s the case.

    Good luck!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s