DataGridView - 索引超出范围。

时间:2016-04-29 15:44:19

标签: vb.net winforms datagridview

在任何人将此作为副本进行分类之前,我确实在StackOverflow和Google周围搜索了我的问题的解决方案,但事实证明这两者都没有成功。

总结一下:我正在构建一个游戏,作为我CS课程中的一个单元的一部分"面向对象编程"。游戏的目的是随机生成飞机,使用计时器扣除燃油油位,然后在燃油达到0时发生碰撞等事件。然后我们必须降落飞机并为它们分配跑道,等等在......

这一切都很好,但是,我正处于我必须列出正在生成的所有平面的阶段,然后让用户选择降落它们。

我最初使用ListView但很快切换到DataGridView,因为我想将一个按钮作为列。

因此,当我点击" Land Plane"时,在生成平面时,并且在DataGridView中进一步显示这些平面。我选择的行中的按钮选择只会跳回到第一行。我向我的讲师询问了他的帮助,他说这是因为燃料的价值随着倒计时不断更新。清除DataGridView后,所选行将重置。

为了解决这个问题,我们添加了两个局部变量来存储选定的行和选定的列。我们检查了所选列是否仍然保留在集合中,当地平面"单击按钮。这是因为当燃料达到0时,它只是从DataGridView中删除该行。

我现在遇到的问题是,我的讲师很困惑的是:

  

未处理的类型' System.ArgumentOutOfRangeException'   发生在mscorlib.dll

     

其他信息:指数超出范围。必须是非负面的   并且小于集合的大小。

处理DataGridView的代码如下:

Public Sub populateDataGV()
    Dim p As New Aircraft

    selRow = -1
    'Populate the data grid view
    If Not (IsNothing(DataGridView1.CurrentCell)) Then
        selRow = DataGridView1.CurrentCell.RowIndex
        selCol = DataGridView1.CurrentCell.ColumnIndex
    End If


    DataGridView1.Rows.Clear()
    DataGridView1.ColumnCount = 2
    DataGridView1.Columns(0).Name = "Flight No"
    DataGridView1.Columns(1).Name = "Fuel"

    For Each p In airport.planeCollection
        Dim row As String() = New String() {p.name, p.getFuelLevel()}
        DataGridView1.Rows.Add(row)
    Next

    Dim RowsToDelete As New List(Of DataGridViewRow)()
    For Each rows As DataGridViewRow In DataGridView1.Rows
        If rows.Cells(1).Value IsNot Nothing AndAlso rows.Cells(1).Value.ToString = "0" Then
            RowsToDelete.Add(rows)
            If selRow = rows.Index Then
                selRow = -1
            End If
        End If
    Next
    For Each rows As DataGridViewRow In RowsToDelete
        DataGridView1.Rows.Remove(rows)
    Next
    RowsToDelete.Clear()

    If selRow <> -1 And selRow <= DataGridView1.Rows.Count - 1 Then
        DataGridView1.CurrentCell = DataGridView1.Rows(selRow).Cells(selCol)
    End If


    'Add button column
    Dim btn As DataGridViewButtonColumn = New DataGridViewButtonColumn()
    btn.HeaderText = "Action"
    btn.Text = "Land Plane"
    btn.UseColumnTextForButtonValue = True
    DataGridView1.Columns.Add(btn)


End Sub

这是抛出错误的地方:

If selRow <> -1 And selRow <= DataGridView1.Rows.Count - 1 Then
        DataGridView1.CurrentCell = DataGridView1.Rows(selRow).Cells(selCol)
    End If

如果有人能够了解实际导致此错误的原因,我将非常感激。

1 个答案:

答案 0 :(得分:2)

您的范围检查可能会出错。

首先,您当前的代码允许selRow小于-2:

If selRow <> -1 And selRow <= DataGridView1.Rows.Count - 1 Then
    DataGridView1.CurrentCell = DataGridView1.Rows(selRow).Cells(selCol)
End If

其次,您不需要设置列...而是将其设置为0或1。

你应该改变

If selRow <> -1 And selRow <= DataGridView1.Rows.Count - 1 Then
    DataGridView1.CurrentCell = DataGridView1.Rows(selRow).Cells(selCol)
End If

If selRow >= 0 And selRow <= DataGridView1.Rows.Count - 1 Then
         DataGridView1.CurrentCell = DataGridView1.Rows(selRow).Cells(1)
End If

这个新代码正确地检查两个值。

此外,您需要从顶部删除:

selRow = -1

最后,为了解决选择正确行的问题,我建议改变:

DataGridView1.Rows.Clear()
DataGridView1.ColumnCount = 2
DataGridView1.Columns(0).Name = "Flight No"
DataGridView1.Columns(1).Name = "Fuel"

For Each p In airport.planeCollection
    Dim row As String() = New String() {p.name, p.getFuelLevel()}
    DataGridView1.Rows.Add(row)
Next

为:

 ' DataGridView1.Rows.Clear()
    If DataGridView1.ColumnCount = 0 Then
        DataGridView1.ColumnCount = 2
        DataGridView1.Columns(0).Name = "Flight No"
        DataGridView1.Columns(1).Name = "Fuel"
    End If

    For Each p In airport.planeCollection
        Dim updated As Boolean = False
        For Each rows As DataGridViewRow In DataGridView1.Rows
            If rows.Cells(0).Value = p.name Then
                rows.Cells(1).Value = p.getFuelLevel
                updated = True
                Exit For
            End If
        Next
        If Not updated Then
            Dim row As String() = New String() {p.name, p.getFuelLevel()}
            DataGridView1.Rows.Add(row)
        End If
    Next

您应该添加/更新,而不是简单地清除和添加。