Problem removing last two rows of DataGridView

I am using VS 2005 Beta 2 and I'm having a problem removing rows from a DataGridView.  The sample code below populates a DataGridView located in an MDI child form with 10 rows.  The first three columns of each row contain buttons to Edit, View or Delete a row.  The Edit and View buttons work under any circumstance but the Delete operation only works on the first 8 deletes and then when either of the remaining two rows has its Delete button clicked, an exception is thrown.

This behavior is interesting, but what is even more interesting is that if I use the spacebar to select the Delete button then I can remove all rows without an exception being thrown. In other words, I only get the exception when clicking on one of the two rows remaining in the grid.  Clicking works on the first 8 clicks of the Delete button.

The exception and the code sample are given below.

Any ideas on why I can delete the last two rows with the spacebar but not with the mouse

Here's the exception:

System.ArgumentOutOfRangeException
Specified argument was out of the range of valid values.
Parameter name: rowIndex

StackTrace:
   at System.Windows.Forms.DataGridView.InvalidateCell(Int32 columnIndex, Int32 rowIndex)
   at System.Windows.Forms.DataGridViewButtonCell.OnLeave(Int32 rowIndex, Boolean throughMouseClick)
   at System.Windows.Forms.DataGridView.SetCurrentCellAddressCore(Int32 columnIndex, Int32 rowIndex, Boolean setAnchorCellAddress, Boolean validateCurrentCell, Boolean throughMouseClick)
   at System.Windows.Forms.DataGridView.OnRemovingRow(Int32 rowIndexDeleted, Point& newCurrentCell, Boolean force)
   at System.Windows.Forms.DataGridViewRowCollection.RemoveAtInternal(Int32 index, Boolean force)
   at System.Windows.Forms.DataGridViewRowCollection.RemoveAt(Int32 index)
   at GridClearTest.ViewForm.deleteRow(Int32 row) in C:\Documents and Settings\ty814c\My Documents\Visual Studio 2005\Projects\GridClearTest\GridClearTest\ViewForm.vb:line 89
   at GridClearTest.ViewForm.onButtonCellClick(DataGridViewCellEventArgs e) in C:\Documents and Settings\ty814c\My Documents\Visual Studio 2005\Projects\GridClearTest\GridClearTest\ViewForm.vb:line 82
   at GridClearTest.ViewForm.grdTests_CellClick(Object sender, DataGridViewCellEventArgs e) in C:\Documents and Settings\ty814c\My Documents\Visual Studio 2005\Projects\GridClearTest\GridClearTest\ViewForm.vb:line 99
   at System.Windows.Forms.DataGridView.OnCellClick(DataGridViewCellEventArgs e)
   at System.Windows.Forms.DataGridView.OnMouseClick(MouseEventArgs e)
   at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
   at System.Windows.Forms.Control.WndProc(Message& m)
   at System.Windows.Forms.DataGridView.WndProc(Message& m)
   at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
   at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
   at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
   at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
   at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32 dwComponentID, Int32 reason, Int32 pvLoopData)
   at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
   at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
   at System.Windows.Forms.Application.Run(ApplicationContext context)
   at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.OnRun()
   at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.DoApplicationModel()
   at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.Run(String[] commandLine)
   at GridClearTest.My.MyApplication.Main(String[] Args) in 17d14f5c-a337-4978-8281-53493378c1071.vb:line 76
   at System.AppDomain.nExecuteAssembly(Assembly assembly, String[] args)
   at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
   at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
   at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Threading.ThreadHelper.ThreadStart()

Here's the code for MainForm.designer.vb:



<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _

Partial Public Class MainForm

Inherits System.Windows.Forms.Form

'Form overrides dispose to clean up the component list.

<System.Diagnostics.DebuggerNonUserCode()> _

Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)

If disposing AndAlso components IsNot Nothing Then

components.Dispose()

End If

MyBase.Dispose(disposing)

End Sub

'Required by the Windows Form Designer

Private components As System.ComponentModel.IContainer

'NOTE: The following procedure is required by the Windows Form Designer

'It can be modified using the Windows Form Designer.

'Do not modify it using the code editor.

<System.Diagnostics.DebuggerStepThrough()> _

Private Sub InitializeComponent()

Me.MenuStrip1 = New System.Windows.Forms.MenuStrip

Me.OpenGridToolStripMenuItem = New System.Windows.Forms.ToolStripMenuItem

Me.MenuStrip1.SuspendLayout()

Me.SuspendLayout()

'

'MenuStrip1

'

Me.MenuStrip1.Items.AddRange(New System.Windows.Forms.ToolStripItem() {Me.OpenGridToolStripMenuItem})

Me.MenuStrip1.Location = New System.Drawing.Point(0, 0)

Me.MenuStrip1.Name = "MenuStrip1"

Me.MenuStrip1.Size = New System.Drawing.Size(748, 24)

Me.MenuStrip1.TabIndex = 2

Me.MenuStrip1.Text = "MenuStrip1"

'

'OpenGridToolStripMenuItem

'

Me.OpenGridToolStripMenuItem.Name = "OpenGridToolStripMenuItem"

Me.OpenGridToolStripMenuItem.Text = "Open Grid"

'

'MainForm

'

Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)

Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font

Me.ClientSize = New System.Drawing.Size(748, 400)

Me.Controls.Add(Me.MenuStrip1)

Me.IsMdiContainer = True

Me.MainMenuStrip = Me.MenuStrip1

Me.Name = "MainForm"

Me.Text = "Delete DataGridView Rows Error Sample"

Me.MenuStrip1.ResumeLayout(False)

Me.ResumeLayout(False)

Me.PerformLayout()

End Sub

Friend WithEvents MenuStrip1 As System.Windows.Forms.MenuStrip

Friend WithEvents OpenGridToolStripMenuItem As System.Windows.Forms.ToolStripMenuItem

End Class


 



Here's the code for MainForm.vb:



Public Class MainForm

Private Sub OpenGridToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles OpenGridToolStripMenuItem.Click

Dim f As Form = New ViewForm()

f.MdiParent = Me

f.Show()

End Sub

End Class


 



Here's the code for ViewForm.designer.vb:



<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _

Partial Public Class ViewForm

Inherits System.Windows.Forms.Form

'Form overrides dispose to clean up the component list.

<System.Diagnostics.DebuggerNonUserCode()> _

Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)

If disposing AndAlso components IsNot Nothing Then

components.Dispose()

End If

MyBase.Dispose(disposing)

End Sub

'Required by the Windows Form Designer

Private components As System.ComponentModel.IContainer

'NOTE: The following procedure is required by the Windows Form Designer

'It can be modified using the Windows Form Designer.

'Do not modify it using the code editor.

<System.Diagnostics.DebuggerStepThrough()> _

Private Sub InitializeComponent()

Me.grdTests = New System.Windows.Forms.DataGridView

Me.DataGridViewButtonColumn1 = New System.Windows.Forms.DataGridViewButtonColumn

Me.DataGridViewButtonColumn2 = New System.Windows.Forms.DataGridViewButtonColumn

Me.DataGridViewButtonColumn3 = New System.Windows.Forms.DataGridViewButtonColumn

Me.DataGridViewTextBoxColumn1 = New System.Windows.Forms.DataGridViewTextBoxColumn

Me.DataGridViewTextBoxColumn2 = New System.Windows.Forms.DataGridViewTextBoxColumn

Me.DataGridViewTextBoxColumn3 = New System.Windows.Forms.DataGridViewTextBoxColumn

Me.DataGridViewTextBoxColumn4 = New System.Windows.Forms.DataGridViewTextBoxColumn

Me.DataGridViewTextBoxColumn5 = New System.Windows.Forms.DataGridViewTextBoxColumn

Me.DataGridViewTextBoxColumn6 = New System.Windows.Forms.DataGridViewTextBoxColumn

Me.DataGridViewTextBoxColumn7 = New System.Windows.Forms.DataGridViewTextBoxColumn

Me.DataGridViewTextBoxColumn8 = New System.Windows.Forms.DataGridViewTextBoxColumn

Me.DataGridViewTextBoxColumn9 = New System.Windows.Forms.DataGridViewTextBoxColumn

Me.DataGridViewTextBoxColumn10 = New System.Windows.Forms.DataGridViewTextBoxColumn

CType(Me.grdTests, System.ComponentModel.ISupportInitialize).BeginInit()

Me.SuspendLayout()

'

'grdTests

'

Me.grdTests.AllowUserToAddRows = False

Me.grdTests.AllowUserToDeleteRows = False

Me.grdTests.AllowUserToOrderColumns = True

Me.grdTests.Columns.Add(Me.DataGridViewButtonColumn1)

Me.grdTests.Columns.Add(Me.DataGridViewButtonColumn2)

Me.grdTests.Columns.Add(Me.DataGridViewButtonColumn3)

Me.grdTests.Columns.Add(Me.DataGridViewTextBoxColumn1)

Me.grdTests.Columns.Add(Me.DataGridViewTextBoxColumn2)

Me.grdTests.Columns.Add(Me.DataGridViewTextBoxColumn3)

Me.grdTests.Columns.Add(Me.DataGridViewTextBoxColumn4)

Me.grdTests.Columns.Add(Me.DataGridViewTextBoxColumn5)

Me.grdTests.Columns.Add(Me.DataGridViewTextBoxColumn6)

Me.grdTests.Columns.Add(Me.DataGridViewTextBoxColumn7)

Me.grdTests.Columns.Add(Me.DataGridViewTextBoxColumn8)

Me.grdTests.Columns.Add(Me.DataGridViewTextBoxColumn9)

Me.grdTests.Columns.Add(Me.DataGridViewTextBoxColumn10)

Me.grdTests.Dock = System.Windows.Forms.DockStyle.Fill

Me.grdTests.Location = New System.Drawing.Point(0, 0)

Me.grdTests.Name = "grdTests"

Me.grdTests.ReadOnly = True

Me.grdTests.Size = New System.Drawing.Size(609, 448)

Me.grdTests.TabIndex = 0

'

'DataGridViewButtonColumn1

'

Me.DataGridViewButtonColumn1.HeaderText = ""

Me.DataGridViewButtonColumn1.Name = "Edit"

Me.DataGridViewButtonColumn1.ReadOnly = True

Me.DataGridViewButtonColumn1.Width = 60

'

'DataGridViewButtonColumn2

'

Me.DataGridViewButtonColumn2.HeaderText = ""

Me.DataGridViewButtonColumn2.Name = "View"

Me.DataGridViewButtonColumn2.ReadOnly = True

Me.DataGridViewButtonColumn2.Width = 60

'

'DataGridViewButtonColumn3

'

Me.DataGridViewButtonColumn3.HeaderText = ""

Me.DataGridViewButtonColumn3.Name = "Delete"

Me.DataGridViewButtonColumn3.ReadOnly = True

Me.DataGridViewButtonColumn3.Width = 60

'

'DataGridViewTextBoxColumn1

'

Me.DataGridViewTextBoxColumn1.HeaderText = "Name"

Me.DataGridViewTextBoxColumn1.Name = "TestName"

Me.DataGridViewTextBoxColumn1.ReadOnly = True

'

'DataGridViewTextBoxColumn2

'

Me.DataGridViewTextBoxColumn2.HeaderText = "Type"

Me.DataGridViewTextBoxColumn2.Name = "TestType"

Me.DataGridViewTextBoxColumn2.ReadOnly = True

'

'DataGridViewTextBoxColumn3

'

Me.DataGridViewTextBoxColumn3.HeaderText = "Date"

Me.DataGridViewTextBoxColumn3.Name = "DateTested"

Me.DataGridViewTextBoxColumn3.ReadOnly = True

'

'DataGridViewTextBoxColumn4

'

Me.DataGridViewTextBoxColumn4.HeaderText = "Sample"

Me.DataGridViewTextBoxColumn4.Name = "SampleName"

Me.DataGridViewTextBoxColumn4.ReadOnly = True

'

'DataGridViewTextBoxColumn5

'

Me.DataGridViewTextBoxColumn5.HeaderText = "Log"

Me.DataGridViewTextBoxColumn5.Name = "LogNumber"

Me.DataGridViewTextBoxColumn5.ReadOnly = True

'

'DataGridViewTextBoxColumn6

'

Me.DataGridViewTextBoxColumn6.HeaderText = "Material"

Me.DataGridViewTextBoxColumn6.Name = "MaterialType"

Me.DataGridViewTextBoxColumn6.ReadOnly = True

'

'DataGridViewTextBoxColumn7

'

Me.DataGridViewTextBoxColumn7.HeaderText = "Class"

Me.DataGridViewTextBoxColumn7.Name = "Classification"

Me.DataGridViewTextBoxColumn7.ReadOnly = True

'

'DataGridViewTextBoxColumn8

'

Me.DataGridViewTextBoxColumn8.HeaderText = "Thick"

Me.DataGridViewTextBoxColumn8.Name = "Thickness"

Me.DataGridViewTextBoxColumn8.ReadOnly = True

'

'DataGridViewTextBoxColumn9

'

Me.DataGridViewTextBoxColumn9.HeaderText = "Height"

Me.DataGridViewTextBoxColumn9.Name = "Height"

Me.DataGridViewTextBoxColumn9.ReadOnly = True

'

'DataGridViewTextBoxColumn10

'

Me.DataGridViewTextBoxColumn10.HeaderText = "Length"

Me.DataGridViewTextBoxColumn10.Name = "Length"

Me.DataGridViewTextBoxColumn10.ReadOnly = True

'

'ViewForm

'

Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)

Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font

Me.ClientSize = New System.Drawing.Size(609, 448)

Me.Controls.Add(Me.grdTests)

Me.Name = "ViewForm"

Me.Text = "Some Data"

CType(Me.grdTests, System.ComponentModel.ISupportInitialize).EndInit()

Me.ResumeLayout(False)

End Sub

Friend WithEvents grdTests As System.Windows.Forms.DataGridView

Friend WithEvents DataGridViewButtonColumn1 As System.Windows.Forms.DataGridViewButtonColumn

Friend WithEvents DataGridViewButtonColumn2 As System.Windows.Forms.DataGridViewButtonColumn

Friend WithEvents DataGridViewButtonColumn3 As System.Windows.Forms.DataGridViewButtonColumn

Friend WithEvents DataGridViewTextBoxColumn1 As System.Windows.Forms.DataGridViewTextBoxColumn

Friend WithEvents DataGridViewTextBoxColumn2 As System.Windows.Forms.DataGridViewTextBoxColumn

Friend WithEvents DataGridViewTextBoxColumn3 As System.Windows.Forms.DataGridViewTextBoxColumn

Friend WithEvents DataGridViewTextBoxColumn4 As System.Windows.Forms.DataGridViewTextBoxColumn

Friend WithEvents DataGridViewTextBoxColumn5 As System.Windows.Forms.DataGridViewTextBoxColumn

Friend WithEvents DataGridViewTextBoxColumn6 As System.Windows.Forms.DataGridViewTextBoxColumn

Friend WithEvents DataGridViewTextBoxColumn7 As System.Windows.Forms.DataGridViewTextBoxColumn

Friend WithEvents DataGridViewTextBoxColumn8 As System.Windows.Forms.DataGridViewTextBoxColumn

Friend WithEvents DataGridViewTextBoxColumn9 As System.Windows.Forms.DataGridViewTextBoxColumn

Friend WithEvents DataGridViewTextBoxColumn10 As System.Windows.Forms.DataGridViewTextBoxColumn

End Class


 



Here's the code for ViewForm.vb:



Imports System.Windows.Forms

Imports System.Collections

Public Class ViewForm

#Region "Member Variables"

Private _rows As Hashtable

#End Region ' Member Variables

#Region "Constructors"

Public Sub New()

InitializeComponent()

End Sub

#End Region ' Constructors

#Region "Initialization"

Private Sub loadHash()

_rows = New Hashtable()

For row As Integer = 1 To 10

Dim colValues(10) As String

For col As Integer = 1 To colValues.GetUpperBound(0)

colValues(col) = "Row " + row.ToString() + ", Column " + col.ToString()

Next

_rows.Add(row, colValues)

Next

End Sub

#End Region ' Initialization

#Region "Grid Loading"

Private Sub loadGrid()

Me.grdTests.Rows.Clear()

For row As Integer = 1 To 10

Me.grdTests.Rows.Add(createGridRow(row))

Next

End Sub

Private Function createGridRow(ByVal rowNumber As Integer) As DataGridViewRow

Dim row As DataGridViewRow = New DataGridViewRow()

row.Tag = rowNumber

row.Cells.Add(createButtonCell("Edit", "Click me to edit this row"))

row.Cells.Add(createButtonCell("View", "Click me to view this row"))

row.Cells.Add(createButtonCell("Delete", "Click me to delete this row"))

Dim cellText() As String = DirectCast(_rows(rowNumber), String())

For col As Integer = 1 To cellText.GetUpperBound(0)

row.Cells.Add(createTextCell(cellText(col)))

Next

Return row

End Function

Private Function createTextCell(ByVal cellText As String) As DataGridViewTextBoxCell

Dim tc As DataGridViewTextBoxCell = New DataGridViewTextBoxCell()

tc.Value = cellText

Return tc

End Function

Private Function createButtonCell(ByVal cellText As String, ByVal tip As String) As DataGridViewButtonCell

Dim tb As DataGridViewButtonCell = New DataGridViewButtonCell

tb.Value = cellText

tb.ToolTipText = tip

Return tb

End Function

#End Region ' Grid Loading

#Region "Grid Event Handling"

Private Sub onButtonCellClick(ByVal e As System.Windows.Forms.DataGridViewCellEventArgs)

Select Case Me.grdTests.CurrentCell.Value.ToString()

Case "Edit"

MsgBox("You selected to Edit row " + (e.RowIndex + 1).ToString())

Case "View"

viewRow(e.RowIndex)

Case "Delete"

deleteRow(e.RowIndex)

End Select

End Sub

Private Sub deleteRow(ByVal row As Integer)

If _rows.ContainsKey(Me.grdTests.Rows(row).Tag) Then

_rows.Remove(Me.grdTests.Rows(row).Tag)

Me.grdTests.Rows.RemoveAt(row)

End If

End Sub

Private Sub viewRow(ByVal row As Integer)

Dim cellText As String = grdTests.Rows(row).Cells(3).Value.ToString

MsgBox("Text in column 4 of row " + (row + 1).ToString() + " is " + cellText)

End Sub

Private Sub grdTests_CellClick(ByVal sender As System.Object, ByVal e As System.Windows.Forms.DataGridViewCellEventArgs) Handles grdTests.CellClick

onButtonCellClick(e)

End Sub

#End Region ' Grid Event Handling

#Region "Form Event Handling"

Private Sub TestListViewForm_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load

loadHash()

loadGrid()

End Sub

#End Region ' Form Event Handling

End Class


 



Answer this question

Problem removing last two rows of DataGridView

  • Davidsfg1

    Mark,

    Do you know if this fix is in the July CTP

    Thanks,
    Brian

  • Barry Gervin

    I'll take a look at this. This could be a serious issue so I was wondering if you could file a bug for it

    thanks,
    -mark
    DataGridView Program Manager
    Microsoft
    This post is provided "as-is"

  • Johan A

    Mark,

    As you requested, I filed a bug report for this issue.  I included a ZIP of a sample that demonstrates this issue.

    -Brian

  • Bene_Ries

    Thanks!

    -mark
    Program Manager
    Microsoft
    This post is provided "as-is"

  • whidbey_boy

    I tried this out on latest bits and I didn't get the error, so it looks like we fixed it.

    thanks for reporting this!
    -mark
    DataGridView Program Manager
    Microsoft
    This post is provided "as-is"

  • Problem removing last two rows of DataGridView