2016-04-29 6 views
3

Прежде чем какие-либо классы это как дубликат, я действительно обыскал как вокруг StackOverflow, так и Google для решения моей проблемы, ни один из них не оказался успешным.DataGridView - индекс был за пределами допустимого диапазона.

Подводя итог: Я создаю игру как часть единицы в своем курсе CS «Объектно-ориентированное программирование». Цель игры состоит в том, чтобы случайным образом создавать самолеты, уровень топлива которых вычитается с использованием таймера, а затем такие события, как авария, срабатывают при достижении топливом 0. Затем нам приходится приземляться на самолеты и назначать им взлетно-посадочные полосы и так далее ...

Все это прекрасно работает, однако я нахожусь на том этапе, когда мне нужно перечислить все самолеты, которые сгенерированы, а затем дать пользователю возможность высадить их.

Первоначально я использовал ListView, но быстро переключился на DataGridView, потому что я хотел иметь кнопку в качестве столбца.

Таким образом, как только плоскости создавались и, кроме того, отображались в DataGridView, всякий раз, когда я нажимал кнопку «Land Plane» в строке моего выбора, выбор просто возвращался в первую строку. Я попросил своего лектора о пощаде, и он заявил, что это потому, что стоимость топлива постоянно обновляется по мере того, как она отсчитывается. Когда DataGridView очищается, выбранная строка сбрасывается.

Чтобы решить эту проблему, мы добавили две локальные переменные для хранения выбранной строки и выбранного столбца. Мы проверили, не был ли выбран выбранный столбец в коллекции, когда была нажата кнопка «Land Plane». Это связано с тем, что когда топливо достигает 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 

Если кто-то может пролить некоторый свет на то, что на самом деле причиной этого Я был бы очень благодарен.

+2

Вы не проверяете 'selCol', который может быть <0 –

+0

... тем более, что он инициализирован' -1' – Plutonix

+0

@Matt Kent. Каковы значения 'selCol' и' selRow', когда возникает исключение? Это должно проливать много света на вашу проблему. – vbnet3d

ответ

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 

Вам следует добавить/обновить, а не просто очистить и добавить.

+1

Спасибо за ваш ответ, он исправил ошибку. Тем не менее, теперь это возвращает меня к моей первоначальной проблеме не повторного выбора правильной строки. Он просто возвращается к самой первой строке DataGridView. Есть идеи? –

+0

Где вы заявляли 'selCol' и' selRow'? Если это «уровень модуля», то значения переносятся, но если он объявлен только в этом «Sub», он будет сбрасываться каждый раз. – vbnet3d

+1

Они оба объявляются непосредственно под 'Public Class Game'. Итак, модуль-уровень. –

Смежные вопросы