views:

3429

answers:

4

I'm using a DataGridView in my WinForms application. My main objective is to make the Enter key not move to the next row in the grid. I still want the enter key to validate and end edit mode.

I found this FAQ entry and subclassed DataGridView to override ProcessDialogKey(). If the key pressed is Enter, I call EndEdit(), otherwise I call base.ProcessDialogKey().

It works great, except the CellValidating event isn't fired.

Currently, I'm just manually calling my validation logic before I call EndEdit, but it seems like I'm missing something.

I guess I could call OnCellValidating, but then I'd be worried I'm missing some other event. What I really want is some flavour of EndEdit() that behaves just like pressing enter on the last row of a grid with adding disabled.

A: 

No, but you can manually fire the CellValidating event. Just create the proper parameters. All events are is a class using the Observer Pattern, they're no different than any other method. If that doesn't work, you can create a KeyPress event on the cell and emulate pressing Enter on the cell, but that may mess with the users UI, just put the carat back where it was.

Malfist
Unfortunately, the EventArgs class for the CellValidating event doesn't have a public constructor.
Don Kirkby
+3  A: 

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)
    {
        if (keyData == Keys.Enter)
        {
            DataGridViewCell currentCell = CurrentCell;
            EndEdit();
            CurrentCell = null;
            CurrentCell = currentCell;
            return true;
        }
        return base.ProcessDialogKey(keyData);
    }
JJO
Yeah, I've seen similar strategies, but it definitely feels like a kludge. I like the idea of setting CurrentCell to null, though. I think the other examples moved to the next row and then back.
Don Kirkby
A: 

thanks for the solution. my version is a slight different from yours, because when i move to the other cell, and my code returns e.cancel=false in the cell validating event, an error will be generated, says that: "operation did not succeed, because the program cannot commit or quit a cell value change". so i put try catch to overcome this problem.

this is my code:

Protected Overrides Function ProcessDialogKey(ByVal keyData As System.Windows.Forms.Keys) As Boolean

    Dim key As Keys = (keyData And Keys.KeyCode)

    If key = Keys.Enter Then
        If MyBase.CurrentCell.ColumnIndex = 1 Then
            Dim iRow As Integer = MyBase.CurrentCell.RowIndex

            MyBase.EndEdit()
            Try
                MyBase.CurrentCell = Nothing
                MyBase.CurrentCell = MyBase.Rows(iRow).Cells(1)
                frmFilter.cmdOk_Click(Me, New EventArgs)
            Catch ex As Exception
            End Try

            Return True
        End If
    End If

    Return MyBase.ProcessDialogKey(keyData)
End Function
A: 

if your DataGridView's DataSource is BindingSouce, do this (put this in your Key processing events):

bds.EndEdit();

if your DataGridView's DataSource is DataTable:

this.BindingContext[dgv.DataSource].EndCurrentEdit();
Michael Buen