views:

367

answers:

2

I have a control which extends the DataGridView control. I am overriding the ProcessDialyKey event and throwing and event of my own, which the container form can respond to as the user types in a cell.

The problem I am finding is that when I fire my "CellEditKeyPress" event from within the DataGridView's ProcessDialogKey method, the Value of the cell I am editing has not yet been updated.

So, as the user types 'a', my CellEditKeyPress event fires but when I obtain the value of the cell, that value is still an empty string. User then types 'b', the value I can obtain is 'a', and so on. My event is always effectively one keypress behind.

Here's some code to illustrate:


    public class MyDataGridView : DataGridView
    {
        public delegate void CellEditKeyPressHandler(Keys keyData, DataGridViewCell currentCell);
        public event CellEditKeyPressHandler CellEditKeyPress;


        protected override bool ProcessDialogKey(Keys keyData)
        {
            if (CellEditKeyPress != null)
            {
                CellEditKeyPress(keyData, this.CurrentCell);
            }

            return base.ProcessDialogKey(keyData);
        }


    }

...and on my form...after wiring up the CellEditKeyPress (in the designer)


        private void myDataGridView1_CellEditKeyPress(Keys keyData, DataGridViewCell currentCell)
        {
            myDataGridView1.EndEdit();

            if (currentCell.Value != null)
            {
                textBox1.Text = currentCell.Value.ToString();
                textBox2.Text = currentCell.FormattedValue.ToString();
            }

            myDataGridView1.BeginEdit(false);
        }

The affect is that the contents of the TextBoxes (1 & 2) is one character behind the contents of the cell I'm editing.

I've tried playing with the order of the ProcessDialogKey method to no avail. (Thinking it may need the base.ProcessDialogKey method called before firing my event, but that didn't change anything.)

I also replaced the "myDataGridView1.EndEdit() with a "this.Validate()" in an attempt to get the control's values up to date, but that made no difference.

Is there a way to ensure I am working with up to date cell content? Am I using the wrong overrides to achieve this?

+1  A: 

This works for me:

    private void myDataGridView1_CurrentCellDirtyStateChanged(object sender, EventArgs e)
    {
        myDataGridView1.EndEdit();

        if (myDataGridView1.CurrentCell.Value != null)
        {
            textBox1.Text = myDataGridView1.CurrentCell.Value.ToString();
            textBox2.Text = myDataGridView1.CurrentCell.FormattedValue.ToString();
        }

        myDataGridView1.BeginEdit(false);

    }
Jacob Seleznev
A: 

CellValidating post here will help you out with this. CellValidating doesn't get called until you change the CurrentCell. So the way I kludged around this was to change the CurrentCell, then switch back to the current one.

protected override bool ProcessDialogKey(Keys keyData)
{
    DataGridViewCell currentCell = CurrentCell;
    EndEdit();
    CurrentCell = null;
    CurrentCell = currentCell;
    if (CellEditKeyPress != null)
    {
        CellEditKeyPress(keyData, this.CurrentCell);
    }
    return base.ProcessDialogKey(keyData);
}
SwDevMan81
Thanks for that. The difficulty is, I want to react to every keypress, not just Enter key, so switching current cell around each time a key is pressed is a little messy.
Stuart Helwig
np, glad you got something that works better.
SwDevMan81