ArgumentOutOfRangeException для Datagridview с 1 ​​строкой - PullRequest
0 голосов
/ 08 мая 2018

У меня странная проблема. У меня есть форма с двумя неограниченными представлениями данных и двумя кнопками. С помощью кнопок я переключаю строки с 1 сетки данных на другую. В начале левая сетка данных заполнена несколькими строками, а правая сетка данных пуста. Поэтому, когда я нажимаю кнопку «Добавить», выбранная строка из левой сетки данных удаляется и добавляется в правую таблицу данных. С помощью кнопки «Удалить» выбранная строка правой сетки данных добавляется обратно в левую сетку данных.

Когда в правой сетке данных есть только одна строка, и я выбираю ее, чтобы «удалить», эта строка удаляется из правой сетки данных и добавляется влево без исключения. Теперь у меня есть ситуация, когда в левой сетке данных есть только одна строка, и когда я нажимаю «Добавить», чтобы переместить ее в правую сетку данных, я получаю исключение ArgumentOutOfRangeException (индекс выходит за границы ...)

Ниже приведен код, который выдает исключение

     For i As Integer = DgvLeft.SelectedRows.Count - 1 To 0 Step -1

         ind = DgvLeft.SelectedRows(i).Index
         If ind > 0 Then
             DgvLeft.Rows.RemoveAt(ind)

         Else
             DgvLeft.Rows.Remove(DgvLeft.SelectedRows(i))
         End If
    Next

Так что я храню индекс строки в переменной. В первый раз я использовал функцию RemoveAt и выдается исключение. Чтобы решить эту проблему, я добавил If-структуру и попробовал функцию Remove. Но опять же исключение.

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

Может кто-нибудь помочь мне с этой странной проблемой?

Ответы [ 3 ]

0 голосов
/ 09 мая 2018

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

Это расширенный фрагмент моего кода в кнопке «Добавить»:

    For i As Integer = DgvLeft.SelectedRows.Count - 1 To 0 Step -1
        'fill the array with the row values
         For j As Integer = 0 To DgvLeft.Columns.Count - 1
             fields(j) = DgvLeft.SelectedRows(i).Cells(DgvLeft.Columns(j).Name).Value
         Next

         'delete the row in datagrid Left
         ind = DgvLeft.SelectedRows(i).Index

         If ind > 0 Then
             DgvLeft.Rows.RemoveAt(ind)

         Else
             DgvLeft.Rows.Remove(DgvLeft.SelectedRows(i))
         End If

         'add the row in datagrid Right
         DgvRight.Rows.Add(fields)
    Next

В приведенном выше фрагменте кода я пытаюсь удалить строку ДО того, как добавлю массив значений из этой строки в другую сетку данных. Когда я посмотрел код кнопки «удалить», я попытался удалить строку ПОСЛЕ того, как я добавил массив значений в другую сетку данных.

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

0 голосов
/ 09 мая 2018

Поскольку опубликованный цикл for «нарушен», я чувствую, что нет необходимости подвергать сомнению то, чего вы пытаетесь достичь здесь. Однако, учитывая то, что вы описали, где на форме есть две сетки и две кнопки (Добавить / Удалить). При нажатии кнопки «Добавить» она перемещает «выбранные строки» из «левой» сетки в «правую» сетку, а затем удаляет строки «выбранных строк» ​​из «левой» сетки. Если нажать кнопку «Удалить», происходит обратный процесс, перемещая «выбранные строки» из правой сетки в левую, а затем удаляет выбранные строки из правой сетки.

Если это правильно, то, кажется, вы делаете это более сложным, чем это должно быть. Это было бы намного проще, если бы вы использовали источник данных какой-либо формы. Однако, чтобы устранить вышеуказанную проблему, кажется, что два метода могут пригодиться для того, что вы хотите сделать. Первый может просто добавить выбранные строки из одной заданной сетки в другую заданную сетку. Следующий метод просто удалит выбранные строки из данной сетки. При реализации этих двух методов кнопка «Добавить» будет…

AddSelectedRows(dgvLeft, dgvRight)
RemoveSelectedRows(dgvLeft)

Кнопка удаления будет ...

AddSelectedRows(dgvRight, dgvLeft)
RemoveSelectedRows(dgvRight)

Прежде чем я объясню приведенный ниже код, следует заметить, что ваш текущий опубликованный код делает огромное программирование "нет-нет" и, без сомнения, является проблемой для вас. Как отмечали Мэри и другие, «изменение значения переменной счетчика в цикле или (как делает код) изменение коллекции, через которую она проходит, редко, если когда-либо делается».

Попробуйте код ниже, это может упростить ситуацию,

Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    AddColumns(dgvLeft)
    AddColumns(dgvRight)
    FillGrid(dgvLeft)
End Sub

Private Sub FillGrid(dgv As DataGridView)
    For i = 0 To 15
        dgv.Rows.Add("C0R" + i.ToString(), "C1R" + i.ToString(), "C2R" + i.ToString())
    Next
End Sub

Private Sub AddColumns(dgv As DataGridView)
    Dim txtCol = New DataGridViewTextBoxColumn()
    txtCol.Name = "Col0"
    txtCol.HeaderText = "Col 0"
    dgv.Columns.Add(txtCol)
    txtCol = New DataGridViewTextBoxColumn()
    txtCol.Name = "Col1"
    txtCol.HeaderText = "Col 1"
    dgv.Columns.Add(txtCol)
    txtCol = New DataGridViewTextBoxColumn()
    txtCol.Name = "Col2"
    txtCol.HeaderText = "Col 2"
    dgv.Columns.Add(txtCol)
End Sub

Private Sub btnAdd_Click(sender As Object, e As EventArgs) Handles btnAdd.Click
    AddSelectedRows(dgvLeft, dgvRight)
    RemoveSelectedRows(dgvLeft)
End Sub


Private Sub btnDelete_Click(sender As Object, e As EventArgs) Handles btnDelete.Click
    AddSelectedRows(dgvRight, dgvLeft)
    RemoveSelectedRows(dgvRight)
End Sub

Private Sub RemoveSelectedRows(dgv As DataGridView)
    Dim totalRowsToDelete = dgv.SelectedRows.Count
    Dim selectedRow As DataGridViewRow
    For i = totalRowsToDelete - 1 To 0 Step -1
        selectedRow = dgv.SelectedRows(i)
        If (Not selectedRow.IsNewRow) Then
            dgv.Rows.RemoveAt(dgv.SelectedRows(i).Index)
        End If
    Next
End Sub

Private Sub AddSelectedRows(sourceDGV As DataGridView, destinationDGV As DataGridView)
    Dim selectedRowCount = sourceDGV.Rows.GetRowCount(DataGridViewElementStates.Selected)
    If (selectedRowCount > 0) Then
        Dim selectedRow As DataGridViewRow
        For i = 0 To selectedRowCount - 1
            selectedRow = sourceDGV.SelectedRows(i)
            If (Not selectedRow.IsNewRow) Then
                destinationDGV.Rows.Add(selectedRow.Cells(0).Value.ToString(),
                      selectedRow.Cells(1).Value.ToString(),
                      selectedRow.Cells(2).Value.ToString())
            End If
        Next
    End If
End Sub
0 голосов
/ 08 мая 2018

Вы изменяете значение DgvLeft.SelectedRows.Count в цикле For. Попробуйте ...

Dim RowCount As Integer = DgvLeft.SelectedRows.Count
For i As Integer = RowCount - 1 To 0 Step -1
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...