Link to home
Start Free TrialLog in
Avatar of BlakeMcKenna
BlakeMcKennaFlag for United States of America

asked on

What is the best DataGridView Event to process Cell activity?

I have a DataGridView that requires User input in a couple of Cells. There seems to be quite a few Cell Events available and I just want to use the right one.

The scenario for this functionality is that the cursor will be placed in a cell awaiting for the User to press/click the Enter Key. At this point, a reading from a PLC will be taken and the value inserted into the Cell. The User also has the option to manually change this reading within the Cell.

With this said, I'm sure there will be more than one Event used. I just want to make sure I'm using the correct ones.

Thanks!
Avatar of Bob Learned
Bob Learned
Flag of United States of America image

I am not quite sure that I understand the events that you will need.  It sounds like you don't need any events with the scenario described.
Avatar of BlakeMcKenna

ASKER

My apologies...your right. Once a value is received, calculations are performed. I also failed to mention that the User also has the ability to manually override the value that was received into the cell with NUMERIC data only.

Once the cell has an accepted value, calculations are made using this value. Hope that helps!

Thanks!
Does anyone have an answer to this question?
Hmmm...I don't remember seeing any E-Mail for this question.  What events have you tried, and what indications are you getting?  The DataGridView control is very buggy, and very difficult to work with when it comes to some types of requirements.
Here is the easiest way for me to explain the problem I'm having. Please take a look at the screen shot.

Editable Columns include "Rin" thru "Final Zero".

Editable Columns allow for a User to manually enter numeric data ONLY...or they simply hit the Enter/Return Key and the application retrieves a decimal value from an Electronic MultiMeter Device. Once the value is retrieved, it needs to advance the cursor to the next COLUMN rather than the next row. The exception to this is when the cursor is in the last Editable Column, at which point it needs to advance to the next ROW and be in the "Rin" column.

I'm thinking this should be fairly simple to accomplish but due to my lack of knowledge with the functionality of the DGV, I'm afraid I've made a "mountain out of a mole hill".

Please help as I am coming down to a deadline.

Thanks!
Screentshot.jpg
Let's try something here--let's add a custom DataGridView that overrides the OnKeyDown method:

Imports System.ComponentModel
Imports System.Windows.Forms

Namespace Sample

	Public Enum EnterBehavior
		NextRow
		NextColumn
	End Enum

	''' <summary>
	'''   A DataGridView with a StandardEnter property which behaves
	'''   like StandardTab.
	''' </summary>
	Public Class StandardEnterDataGridView
		Inherits DataGridView
		''' <summary>
		''' Sets the behavior for the {Enter} key.  Either next row (default),
		''' or next column.
		''' </summary>
		<Category("Behavior"), Description("Disable default edit/advance to next row behavior of of the Enter key.")> _
		Public Property EnterKeyBehavior() As EnterBehavior
			Get
				Return m_EnterKeyBehavior
			End Get
			Set
				m_EnterKeyBehavior = Value
			End Set
		End Property
		Private m_EnterKeyBehavior As EnterBehavior

		Protected Overrides Sub OnKeyDown(e As KeyEventArgs)
			If EnterKeyBehavior = EnterBehavior.NextColumn AndAlso e.KeyCode = Keys.Enter Then
				e = New KeyEventArgs(Keys.Tab)
			End If

			MyBase.OnKeyDown(e)
		End Sub
	End Class
End Namespace

Open in new window

I know this is a dumb question but Do I need to create a new Class Module or can I just add this to my Form Class? I'm not real good with inheritance. How do I implement this?
The difference between overriding the default behavior of the DataGridView, and using an event handler is the amount of control.

For an event handler, you would attach to the KeyPress event handler, check for an {Enter} key, and set event arguments "e.Handled = true", and then use SendKeys.Send with a {Tab} key.

If you can't translate that description to code, I will help you, but I would like to see you try first.
Ok, but am I using the same code that is in the KeyDown Event or do I need to recode from scratch? I do want to learn this but I'm really under a time constraint.
Time pressures are part of the job...

It's pretty simple, once you get the hang of it:

    Private Sub DataGridView1_KeyPress(sender As Object, e As KeyPressEventArgs) Handles DataGridView1.KeyPress
        If e.KeyChar = Chr(13) Then
            e.Handled = True
            SendKeys.Send("{TAB}")
        End If
    End Sub

Open in new window

Ok, I tried the above code snippet and the cursor advances horizontally, however, it skips a cell in the process.
If you comment out the SendKeys call, does it still move the current cell?  If so, then we need to find out what causes that behavior, and stop it from happening.
I commented out the SendKey Call and it advanced the cursor 1 row down and 1 column to the right. Here is the code that I'm using and I'm sure it's overkill but it's what this mind of mine thinks. Any reference to the variable "blnOEM" is always true for now.


    Private Sub dgvLoadTests_CellEndEdit(sender As Object, e As DataGridViewCellEventArgs) Handles dgvLoadTests.CellEndEdit
        Try
            EH.strRetVal = ""

            If blnOEM Then
                If colIDX < dgvLoadTests.Columns.Count - 3 Then
                    dgvLoadTests.CurrentCell = dgvLoadTests(colIDX + 1, rowIDX)
                Else
                    If rowIDX = dgvLoadTests.Rows.Count - 1 Then
                        dgvLoadTests.CurrentCell = dgvLoadTests(colIDX, rowIDX)
                    Else
                        dgvLoadTests.CurrentCell = dgvLoadTests(2, rowIDX + 1)
                    End If
                End If
            Else
                If rowIDX < dgvLoadTests.Rows.Count - 1 Then
                    dgvLoadTests.CurrentCell = dgvLoadTests(colIDX, rowIDX + 1)
                Else
                    dgvLoadTests.CurrentCell = dgvLoadTests(colIDX, rowIDX)
                End If
            End If

        Catch ex As Exception
            EH.strRetVal = gfrmID & "/dgvLoadTests_CellEndEdit() - " & ex.Message
        End Try

        EH.ProcessMessages(Me, sbr, EH.strRetVal)
    End Sub
    '
    '
    '
    Private Sub dgvLoadTests_CellMouseClick(sender As Object, e As DataGridViewCellMouseEventArgs) Handles dgvLoadTests.CellMouseClick
        Try
            iRow = dgvLoadTests.CurrentRow.Index
            EH.strRetVal = ""

        Catch ex As Exception
            EH.strRetVal = gfrmID & "/dgvLoadTests_CellMouseClick() - " & ex.Message
        End Try

        EH.ProcessMessages(Me, sbr, EH.strRetVal)
    End Sub
    '
    '
    '
    Private Sub dgvLoadTests_CellValidating(sender As Object, e As DataGridViewCellValidatingEventArgs) Handles dgvLoadTests.CellValidating
        Try
            EH.strRetVal = ""

            rowIDX = dgvLoadTests.CurrentCellAddress.Y  'Get Row Index
            colIDX = dgvLoadTests.CurrentCellAddress.X  'Get Column Index

            If dgvLoadTests.Item(e.ColumnIndex, e.RowIndex).IsInEditMode Then
                If Not dgvLoadTests.Item(e.ColumnIndex, e.RowIndex).ValueType Is GetType(Decimal) Then
                    Dim c As Control = dgvLoadTests.EditingControl
                    Dim cell As DataGridViewCell = dgvLoadTests.CurrentCell

                    If Not Decimal.TryParse(c.Text, Nothing) Then
                        If c.Text = "" Then
                        Else
                            EH.strRetVal = "Invalid Numeric Value!" & "~I"
                            e.Cancel = True
                        End If
                    Else
                        If blnOEM Then
                            Select Case e.RowIndex
                                Case 0
                                    cell.Value = Format(c.Text, c.Text) 'Don't format the Load Values
                                Case Else
                                    cell.Value = Format(c.Text, GetDecimalPlaces(c.Text))
                            End Select
                        Else
                            Select Case e.ColumnIndex
                                Case 1
                                    cell.Value = Format(c.Text, c.Text) 'Don't format the Load Values
                                Case Else
                                    cell.Value = Format(c.Text, GetDecimalPlaces(c.Text))
                            End Select
                        End If
                    End If
                    dgvLoadTests.CancelEdit()
                End If
            End If

        Catch ex As Exception
            EH.strRetVal = gfrmID & "/dgvLoadTests_CellValidating() - " & ex.Message
        End Try

        EH.ProcessMessages(Me, sbr, EH.strRetVal)
    End Sub
    '
    '
    '
    Private Sub dgvLoadTests_KeyDown(sender As Object, e As KeyEventArgs) Handles dgvLoadTests.KeyDown
        Try
            EH.strRetVal = ""
            nonNumbered = False

            Select Case e.KeyCode
                Case Keys.Enter Or Keys.Return
                    rowIDX = dgvLoadTests.CurrentCellAddress.Y  'Get Row Index
                    colIDX = dgvLoadTests.CurrentCellAddress.X  'Get Column Index
                    If blnOEM Then
                        Select Case colIDX
                            Case 0 To 1                             'Columns 0 & 1
                            Case dgvLoadTests.Columns.Count - 2     'The last editable column
                                If rowIDX < dgvLoadTests.Rows.Count - 1 Then        'This is any row other than the last row in the Grid
                                    dgvLoadTests.CurrentCell = dgvLoadTests(2, rowIDX + 1)
                                Else
                                    dgvLoadTests.Rows(rowIDX).Cells(colIDX).Value = GetDecimalPlaces("00.0000") 'Get Multimeter Reading
                                End If
                            Case Else
                                If rowIDX = dgvLoadTests.Rows.Count - 1 Then    'This is the last row
                                    If Not colIDX = dgvLoadTests.Columns.Count - 3 Then 'This is the last editable column
                                        dgvLoadTests.CurrentCell = dgvLoadTests(colIDX + 1, rowIDX)
                                    End If
                                    dgvLoadTests.Rows(rowIDX).Cells(colIDX).Value = GetDecimalPlaces("00.0000") 'Get Multimeter Reading
                                Else
                                    If colIDX >= 2 And colIDX < dgvLoadTests.Columns.Count - 3 Then
                                        dgvLoadTests.CurrentCell = dgvLoadTests(colIDX + 1, rowIDX)
                                        dgvLoadTests.Rows(rowIDX).Cells(colIDX).Value = GetDecimalPlaces("00.0000") 'Get Multimeter Reading
                                    ElseIf colIDX = dgvLoadTests.Columns.Count - 3 Then
                                        dgvLoadTests.CurrentCell = dgvLoadTests(2, rowIDX + 1)
                                        dgvLoadTests.Rows(rowIDX).Cells(colIDX).Value = GetDecimalPlaces("00.0000") 'Get Multimeter Reading
                                    Else
                                        dgvLoadTests.CurrentCell = dgvLoadTests(colIDX + 1, rowIDX)
                                        dgvLoadTests.Rows(rowIDX).Cells(colIDX).Value = GetDecimalPlaces("00.0000") 'Get Multimeter Reading
                                    End If
                                End If
                        End Select
                    Else    'Take this branch for Non-OEM Tests (a single Sensor test)
                        Select Case rowIDX
                            Case 0
                                If colIDX = 1 Then
                                    dgvLoadTests.Rows(rowIDX).Cells(colIDX).Value = GetDecimalPlaces("00.0000") 'Get Multimeter Reading
                                End If
                            Case dgvLoadTests.Rows.Count - 1    'TEST IS FINISHED at this point
                                'dgvLoadTests.Rows(rowIDX).Cells(colIDX).Value = GetDecimalPlaces("00.0000") 'Get Multimeter Reading
                            Case Else
                                dgvLoadTests.Rows(rowIDX).Cells(colIDX).Value = GetDecimalPlaces("00.0000") 'Get Multimeter Reading
                        End Select
                    End If
                Case Keys.D0 To Keys.D9
                Case Keys.NumPad0 To Keys.NumPad9
                Case Keys.Delete
                    nonNumbered = False
                    dgvLoadTests.Rows(rowIDX).Cells(colIDX).Value = ""
                Case Keys.Back
                Case Else
                    nonNumbered = True
            End Select

        Catch ex As Exception
            EH.strRetVal = gfrmID & "/dgvLoadTests_KeyDown() - " & ex.Message
        End Try

        EH.ProcessMessages(Me, sbr, EH.strRetVal)
    End Sub
    '
    '
    '
    Private Sub dgvLoadTests_KeyPress(sender As Object, e As KeyPressEventArgs) Handles dgvLoadTests.KeyPress
        Try
            rowIDX = dgvLoadTests.CurrentCell.RowIndex
            colIDX = dgvLoadTests.CurrentCell.ColumnIndex

            If e.KeyChar = Chr(13) Then
                e.Handled = True
                'SendKeys.Send("{TAB}")

                If rowIDX = dgvLoadTests.Rows.Count - 1 Then
                Else
                End If
            End If

            EH.strRetVal = ""

        Catch ex As Exception
            EH.strRetVal = gfrmID & "/dgvLoadTests_KeyPress() - " & ex.Message
        End Try

        EH.ProcessMessages(Me, sbr, EH.strRetVal)
    End Sub
    '
    '
    '
    Private Sub dgvLoadTests_MouseClick(sender As Object, e As MouseEventArgs) Handles dgvLoadTests.MouseClick
        Try
            EH.strRetVal = ""

            If Not blnManual Then
                Dim col As Integer = dgvLoadTests.CurrentCell.ColumnIndex

                If col = 5 Then
                    SetMatrix(Me.Name, cmbOutputUnit.Text, FaultyDeviceName)
                End If
            End If

        Catch ex As Exception
            EH.strRetVal = gfrmID & "/dgvLoadTests_MouseClick() - " & ex.Message
        End Try

        EH.ProcessMessages(Me, sbr, EH.strRetVal)
    End Sub
I would try commenting out the code in the dgvLoadTests_KeyDown event handler that handles the Enter key:

   Case Keys.Enter Or Keys.Return
                    rowIDX = dgvLoadTests.CurrentCellAddress.Y  'Get Row Index
                    colIDX = dgvLoadTests.CurrentCellAddress.X  'Get Column Index

...

Open in new window

I tried commenting out the entire code in the KeyDown for the Keys.Enter or Keys.Return and that had no effect.

I also tried commenting out the 2 lines that you have in your previous post and that didn't work either.

I'm spending way to much time on this.
Well, remember that I am on the outside looking in, and the DataGridView is a strange beast.

If you comment out the SendKeys, and the code in the KeyDown for the {Enter} key, what happens?
That's the current scenario and it's still acting weird. Advancing 1 row and 1 column to the right still.
I also see where you are changing CurrentCell in the dgvLoadTests_CellEndEdit event handler.  Does this behavior happen when you are in edit mode, or not in edit mode?
I don't understand the EditMode Events real well. When does the CellEndEdit Event fire? At what point am I not in EditMode? Below is the code that I have so far. It's current functionality is that when I enter a value in the cell in all the rows except for the last, the cursor advances to the next column, like it's suppose to. When I hit the enter key with nothing in the cell, it simply advances to the next row. When I'm in the last row and enter a value, the cursor advances to the next column, however, the value in the previous cell disappears. Below is the code that I have as of right now.

        Private Sub dgvLoadTests_CellEndEdit(sender As Object, e As DataGridViewCellEventArgs) Handles dgvLoadTests.CellEndEdit
        Try
            If colIDX = dgvLoadTests.Columns.Count - 1 Then
                If rowIDX < dgvLoadTests.Rows.Count - 1 Then
                    dgvLoadTests.CurrentCell = dgvLoadTests(0, rowIDX + 1)
                End If
            Else
                If rowIDX < dgvLoadTests.Rows.Count - 1 Then
                    SendKeys.Send("{up}")
                End If
                dgvLoadTests.CurrentCell = dgvLoadTests(colIDX + 1, rowIDX)
            End If

        Catch ex As Exception
            EH.strRetVal = gfrmID & "/dgvLoadTests_CellEndEdit() - " & ex.Message
        End Try
    End Sub
    '
    '
    '
    Private Sub dgvLoadTests_CellValidating(sender As Object, e As DataGridViewCellValidatingEventArgs) Handles dgvLoadTests.CellValidating
        Try
            EH.strRetVal = ""

            rowIDX = dgvLoadTests.CurrentCellAddress.Y  'Get Row Index
            colIDX = dgvLoadTests.CurrentCellAddress.X  'Get Column Index

            If dgvLoadTests.Item(e.ColumnIndex, e.RowIndex).IsInEditMode Then
                If Not dgvLoadTests.Item(e.ColumnIndex, e.RowIndex).ValueType Is GetType(Decimal) Then
                    Dim c As Control = dgvLoadTests.EditingControl
                    Dim cell As DataGridViewCell = dgvLoadTests.CurrentCell

                    If Not Decimal.TryParse(c.Text, Nothing) Then
                        If c.Text = "" Then
                        Else
                            EH.strRetVal = "Invalid Numeric Value!" & "~I"
                            e.Cancel = True
                        End If
                    Else
                        Select Case e.RowIndex
                            Case 0
                                cell.Value = Format(c.Text, c.Text) 'Don't format the Load Values
                            Case Else
                                cell.Value = Format(c.Text, GetDecimalPlaces(c.Text))
                        End Select
                    End If
                    dgvLoadTests.CancelEdit()
                End If
            End If

        Catch ex As Exception
            EH.strRetVal = gfrmID & "/dgvLoadTests_CellValidating() - " & ex.Message
        End Try

        EH.ProcessMessages(Me, sbr, EH.strRetVal)
    End Sub
    '
    '
    '
    Private Sub dgvLoadTests_KeyDown(sender As Object, e As KeyEventArgs) Handles dgvLoadTests.KeyDown
        Try
            nonNumbered = False

            Select Case e.KeyCode
                Case Keys.Enter
                    rowIDX = dgvLoadTests.CurrentCellAddress.Y  'Get Row Index
                    colIDX = dgvLoadTests.CurrentCellAddress.X  'Get Column Index
                Case Keys.D0 To Keys.D9
                Case Keys.NumPad0 To Keys.NumPad9
                Case Keys.Delete
                    nonNumbered = False
                    dgvLoadTests.Rows(rowIDX).Cells(colIDX).Value = ""
                Case Keys.Back
                Case Else
                    nonNumbered = True
            End Select

        Catch ex As Exception
            EH.strRetVal = gfrmID & "/dgvLoadTests_KeyDown() - " & ex.Message
        End Try
    End Sub
    '
    '
    '
    Private Sub dgvLoadTests_KeyPress(sender As Object, e As KeyPressEventArgs) Handles dgvLoadTests.KeyPress
        Try
            If Not IsNumeric(e.KeyChar) Then
                e.Handled = True
            ElseIf e.KeyChar = Microsoft.VisualBasic.ChrW(Keys.Return) Or e.KeyChar = Microsoft.VisualBasic.ChrW(Keys.Enter) Then
                    If blnOEM Then
                        If colIDX = dgvLoadTests.Columns.Count - 2 Then
                            If rowIDX < dgvLoadTests.Rows.Count - 1 Then
                                dgvLoadTests.CurrentCell = dgvLoadTests(2, rowIDX + 1)
                            Else
                                'dgvLoadTests.Rows(rowIDX).Cells(colIDX).Value = GetDecimalPlaces("00.0000") 'Get Multimeter Reading
                            End If
                        Else
                            If rowIDX = dgvLoadTests.Rows.Count - 1 Then
                                If colIDX = dgvLoadTests.Columns.Count - 3 Then
                                    'dgvLoadTests.Rows(rowIDX).Cells(colIDX).Value = GetDecimalPlaces("00.0000") 'Get Multimeter Reading. TEST IS FINISHED at this point
                                Else
                                    'dgvLoadTests.Rows(rowIDX).Cells(colIDX).Value = GetDecimalPlaces("00.0000") 'Get Multimeter Reading
                                    dgvLoadTests.CurrentCell = dgvLoadTests(colIDX + 1, rowIDX)
                                End If
                            Else
                                If colIDX >= 1 And colIDX < dgvLoadTests.Columns.Count - 2 Then
                                    'dgvLoadTests.Rows(rowIDX).Cells(colIDX).Value = GetDecimalPlaces("00.0000") 'Get Multimeter Reading
                                End If

                                If colIDX = dgvLoadTests.Columns.Count - 3 Then
                                    dgvLoadTests.CurrentCell = dgvLoadTests(2, rowIDX + 1)
                                Else
                                    dgvLoadTests.CurrentCell = dgvLoadTests(colIDX + 1, rowIDX)
                                End If
                            End If
                        End If
                    Else    'Take this branch for Non-OEM Tests (a single Sensor test)
                    End If
                End If

        Catch ex As Exception
            EH.strRetVal = gfrmID & "/dgvLoadTests_KeyPress() - " & ex.Message
        End Try

        EH.ProcessMessages(Me, sbr, EH.strRetVal)
    End Sub
Here is link to the DataGridView events, with a short description for each:

DataGridView Events
http://msdn.microsoft.com/en-us/library/system.windows.forms.datagridview_events(v=vs.110).aspx

CellBeginEdit -- Occurs when edit mode starts for the selected cell.

The point at which the edit mode starts, depends on the EditMode property.

DataGridView.EditMode Property
http://msdn.microsoft.com/en-us/library/system.windows.forms.datagridview.editmode(v=vs.110).aspx

EditOnEnter      
Editing begins when the cell receives focus. This mode is useful when pressing the TAB key to enter values across a row, or when pressing the ENTER key to enter values down a column.

EditOnF2
Editing begins when F2 is pressed while the cell has focus. This mode places the selection point at the end of the cell contents.

EditOnKeystroke
Editing begins when any alphanumeric key is pressed while the cell has focus.

EditOnKeystrokeOrF2
Editing begins when any alphanumeric key or F2 is pressed while the cell has focus.

EditProgrammatically
Editing begins only when the BeginEdit method is called.
There is just so many different events to choose from which takes me back to my original question. It seems you can do the same thing in multiple events.

The scenario for this functionality is that the cursor will be placed in a cell awaiting for the User to press/click the Enter Key. At this point, a reading from a PLC (there is code that automatically retrieves a decimal value) will be taken and the value inserted into the Cell. The User also has the option to manually change this retrieved value by entering their own numeric value.

With the above requirement, how would YOU code this? Keep in mind that the cursor has to advance horizontally and not vertically.
Another issue is that there is a confusing array of events that can conflict, especially if you require a lot of different functionality.  Key events during EditMode can really complicate the situation.

If you are asking me how I would approach this problem, then we need to revisit a previous comment, with more detail.

Here is some code to show how it all works.
Form1.vb:

Public Class Form1

    Private ReadOnly _dataSource As Object(,) = New Object(9, 4) {}
    
    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        DataGridView1.VirtualMode = True
        DataGridView1.RowCount = 5
        DataGridView1.ColumnCount = 5
    End Sub

    Private Sub DataGridView1_CellValueNeeded(sender As Object, e As DataGridViewCellValueEventArgs) Handles DataGridView1.CellValueNeeded
        e.Value = _dataSource(e.RowIndex, e.ColumnIndex)
    End Sub

    Private Sub DataGridView1_CellValuePushed(sender As Object, e As DataGridViewCellValueEventArgs) Handles DataGridView1.CellValuePushed
        _dataSource(e.RowIndex, e.ColumnIndex) = e.Value
    End Sub

End Class

Open in new window

CustomDataGridView.vb:

Imports System.ComponentModel
Imports System.Windows.Forms

Public Enum EnterBehavior
    NextRow
    NextColumn
End Enum

''' <summary>
'''   A DataGridView with a StandardEnter property which behaves
'''   like StandardTab.
''' </summary>
Public Class CustomDataGridView
    Inherits DataGridView

    ''' <summary>
    ''' Sets the behavior for the {Enter} key.  Either next row (default),
    ''' or next column.
    ''' </summary>
    <Category("Behavior"), Description("Disable default edit/advance to next row behavior of of the Enter key.")> _
    Public Property EnterKeyBehavior() As EnterBehavior

    Protected Overrides Function ProcessCmdKey(ByRef msg As Message, ByVal keyData As Keys) As Boolean
        If keyData = Keys.Enter Then
            SendKeys.Send("{TAB}")
            Return True
        End If
        Return False
    End Function

End Class

Open in new window

When you build an application with a custom control included, the custom control should be added to the ToolBox, so that you can drag and drop the control onto the Form designer surface.

The ProcessCmdKey works for either the edit mode, or the regular mode.
Here is a good resource to explain the DataGridView:

DataGridView FAQ Google Document
https://docs.google.com/file/d/0B5SkDFb3doulcFp6VU5RMDVCUkE/edit
Thanks, I'll study this for awhile and see what I can make of it.
I'm just not getting it!
ASKER CERTIFIED SOLUTION
Avatar of Bob Learned
Bob Learned
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Your link is requiring me to logon. I tried using my regular login ID and it wouldn't work.

Nevermind...my bad! I'm in...
Ok,

Is VirtualMode used for Databound dgv's only? I tried setting my grid's virtualmode to true and I lost all my header info. Certain cells of my Grid is pre-populated  based on User Input. A button is pressed and all the logic is in the Button's click event. Can that be moved to the CellValueNeeded Event? If so, how can it be triggered based on User Input? Where can I check to make sure only numeric data is input?

Thanks!
When you work with virtual mode, your program is required to supply all information, and store the data entered.  It was an easy way to show you an example of how the DataGridView works when entering values in the cells, and pressing the {Enter} key.
LearnedOne,

Regarding post ID: 39721660, I was wondering about the Function "ProcessCmdKey"?

Is there anyway of being able to toggle the SendKey command to "{ENTER}" under one condition and "{TAB}" under another condition? I only say this because I tried to use a global boolean variable and it just hung my app.

The scenario was that my grid can be presented in 2 different ways, one showing columnar data and the other showing row data. When it's in Row Data mode, hitting the enter key should move the cursor down a row (which is it's default anyway) rather than horizontally.
I had an enumeration to control the behavior (EnterKeyBehavior), but it didn't make it into the logic.

Here is the change, adding a check for the EnterKeyBehavior property.  You can change that on the Form designer where the control is hosted.

 Protected Overrides Function ProcessCmdKey(ByRef msg As Message, ByVal keyData As Keys) As Boolean
        If EnterKeyBehavior = EnterKey.NextColumn AndAlso keyData = Keys.Enter Then
            SendKeys.Send("{TAB}")
            Return True
        End If
        Return False
    End Function

Open in new window

I put the above code in your CustomDataGridView class and it said "EnterKey" was undeclared. I'm correct in making this change in YOUR code right? Please correct me if I'm wrong.

Thanks!
At the top of the class module was the enumeration declaration, that you didn't notice:

Public Enum EnterBehavior
    NextRow
    NextColumn
End Enum

Open in new window

No, actually I did see that. But I tried to alter your original code (ID: 39721660) using the new code in post ID: 39726818. When I tried this, the "EnterKey" object was undeclared.
Can you show me the code please?
Here is the code that I inserted into my KeyUp Event.

            If gblnOEM Then
                cDGV.EnterKeyBehavior = EnterBehavior.NextColumn
            Else
                cDGV.EnterKeyBehavior = EnterBehavior.NextRow
            End If

Open in new window



Your code is below. I'm getting and undeclared warning on the "EnterKey" object within the ProcessCmdKey Function.

Imports System.ComponentModel
Imports System.Windows.Forms

Public Enum EnterBehavior
    NextRow
    NextColumn
End Enum

''' <summary>
'''   A DataGridView with a StandardEnter property which behaves
'''   like StandardTab.
''' </summary>
Public Class CustomDataGridView
    Inherits DataGridView

    ''' <summary>
    ''' Sets the behavior for the {Enter} key.  Either next row (default),
    ''' or next column.
    ''' </summary>
    <Category("Behavior"), Description("Disable default edit/advance to next row behavior of of the Enter key.")> _
    Public Property EnterKeyBehavior() As EnterBehavior

    Protected Overrides Function ProcessCmdKey(ByRef msg As Message, ByVal keyData As Keys) As Boolean
        If EnterKeyBehavior = EnterKey.NextColumn AndAlso keyData = Keys.Enter Then
            SendKeys.Send("{TAB}")
            Return True
        End If
        Return False
    End Function
End Class

Open in new window

Sorry for my dyslexia:

EnterBehavior.NextColumn
No worries...that worked too!

Thanks again for your help!