Hi,
I am facing a bug while using Enter key for DataGridView (DGV) navigation if the form containing theDGV is an MDI child. However, the code is working well if used from the non-MDI child form.
The problem arises when user presses Enter key on the last column of the last row of DGV to leave the DGV control after typing something (means having cell in edit mode). The focus seems to be left from DGV to the next control which is a Button but then the Enter key doesn't fire the Click event of the Button. However the code is working fine, if the user leaves the DGV pressing Enter but without typing anything on the last cell (means having cell in not edit mode).
Steps to create a sample project:
1. Start New Project with GridEnterNavigation as Name
2. Delete the existing Form1
3. Add new blank form having frmParent as Name
4. Add second new blank form having frmChild as Name
5. Copy the code provided in Listing 1 below to the code file of frmParent form
6. Copy the code provided in Listing2 below to the code file of frmChild form
7. Set the project's startup form as frmParent
Steps to produce a problem:
1. Start the application
2. Click the Open Form button on the Main Form
3. Navigate through the DGV on child form using Enter key
4. Put some data in the last column of the last row and press Enter to end the editing
Now the focus will seemed to be on the button (control next to the DGV) but pressing Enter there will not fire the Click event of the button. However, if you'll leave the last row/last column without modifying it, it would work fine.
However, if you will run the project with the frmChild as the startup form this will work OK.
Listing 1
Public Class frmParent
Friend WithEvents btnOpenForm As Button
Private Sub btnOpenForm_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
Dim frm As New frmChild()
frm.MdiParent = Me
frm.StartPosition = FormStartPosition.CenterScreen
frm.Text = "Child Form"
frm.Show()
End Sub
Private Sub frmParent_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Me.Text = "Main Form"
Me.WindowState = FormWindowState.Maximized
Me.IsMdiContainer = True
CreateControls()
End Sub
Private Sub CreateControls()
btnOpenForm = New System.Windows.Forms.Button
btnOpenForm.Name = "btnOpenForm"
btnOpenForm.Text = "Open Form"
btnOpenForm.TabStop = False
btnOpenForm.Location = New Point(12, 12)
AddHandler btnOpenForm.Click, AddressOf btnOpenForm_Click
Me.Controls.Add(btnOpenForm)
End Sub
End Class
Listing 2
Public Class frmChild
Friend WithEvents dgv As GridEnterNavigation.dgvControl
Friend WithEvents btn As System.Windows.Forms.Button
Private Sub frmChild_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Me.CreateControls()
Dim dt As New DataTable()
dt.Columns.Add(New DataColumn("Name", GetType(String)))
dt.Columns.Add(New DataColumn("Amount", GetType(Decimal)))
dt.Rows.Add(dt.NewRow())
dgv.AllowUserToAddRows = False
dgv.DataSource = dt
End Sub
Private Sub CreateControls()
'
'dgv
'
Me.dgv = New GridEnterNavigation.dgvControl
Me.dgv.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize
Me.dgv.Location = New System.Drawing.Point(12, 12)
Me.dgv.Name = "dgv"
Me.dgv.Size = New System.Drawing.Size(268, 204)
Me.dgv.TabIndex = 0
'
'btn
'
Me.btn = New System.Windows.Forms.Button
Me.btn.Location = New System.Drawing.Point(12, 222)
Me.btn.Name = "btn"
Me.btn.Size = New System.Drawing.Size(75, 23)
Me.btn.TabIndex = 1
Me.btn.Text = "Click"
Me.btn.UseVisualStyleBackColor = True
AddHandler btn.Click, AddressOf btn_Click
Me.Controls.Add(dgv)
Me.Controls.Add(btn)
End Sub
Private Sub btn_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
MessageBox.Show("Child Form's Button clicked")
End Sub
End Class
Public Class dgvControl
Inherits DataGridView
Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
MyBase.OnPaint(e)
'Add your custom paint code here
End Sub
Protected Overloads Overrides Function ProcessDialogKey(ByVal keyData As Keys) As Boolean
'cell is in Edit mode
If keyData = Keys.Enter Then
keyData = Keys.Tab
End If
Return MyBase.ProcessDialogKey(keyData)
End Function
Protected Overloads Overrides Function ProcessCmdKey(ByRef msg As Message, ByVal keyData As Keys) As Boolean
'cell is not in Edit mode
If keyData = Keys.Enter Then
keyData = Keys.Tab
msg.LParam = CType(&HF0001, IntPtr)
msg.WParam = CType(&H9, IntPtr)
If Me.CurrentCell.RowIndex = Me.RowCount - 1 And Me.CurrentCell.ColumnIndex = Me.ColumnCount - 1 Then
Me.FindForm.SelectNextControl(Me, True, True, True, True)
Return False
End If
End If
Return MyBase.ProcessCmdKey(msg, keyData)
End Function
End Class
Share your knowledge. It's a way to achieve immortality. - Dalai Lama MSN: kalilani@hotmail.com - Yahoo: kalilanipk