I've looked online and I've seen a lot of different posts of similar stuff. My code moves the rows correctly.
This is what happens: I press either the UP or Down Buttons, the selected rows moves accordingly.
If I click on the Row that I just moved and I try to move it back, it moves it in the DataTable's DefaultView sort order but the position change is NOT reflected in the DataGridView.
If I select a Row I've never moved, it will move it and the DataGridView will reflect it, but once again if I choose that same row and try to move it back, this change is not reflected in the View, but the DataTable is updated.
I've tried to ResetBindings
, DataGridView.Refresh
, reset the DataSource: none of this works.
Anyone know why this happens and how i can fix it so it reflects the changes every time?
Private Sub UpBtn_Click(sender As Object, e As EventArgs) Handles UpBtn.Click
MoveUpDataRow(StepDGV.CurrentRow.Index)
End Sub
Private Sub MoveUpDataRow(RowIndex As Integer)
Dim OriginalStepNumber As Integer
Dim dv As DataView = StepsData.DefaultView
OriginalStepNumber = CInt(StepDGV.Rows(RowIndex).Cells("StepIDLS").Value)
If RowIndex = 0 Then
'dv(RowIndex - 1)("StepIDLS") = OriginalStepNumber + 1
'dv(RowIndex)("StepIDLS") = OriginalStepNumber - 1
exit Sub
Else
dv(RowIndex - 1).BeginEdit()
dv(RowIndex - 1)("StepIDLS") = OriginalStepNumber
'dv(RowIndex)("StepIDLS") = RowIndex-1
dv(RowIndex - 1).EndEdit()
dv(RowIndex).BeginEdit()
dv(RowIndex)("StepIDLS") = OriginalStepNumber - 1
'dv(RowIndex)("StepIDLS") = RowIndex-1
dv(RowIndex).EndEdit()
End If
dv.Sort = "StepIDLS ASC"
' StepDGV.Rows(RowIndex).Selected = true
'StepDGV.DataSource = StepsData
'StepDGV.Refresh()
StepDGV.ResetBindings()
StepDGV.Refresh()
End Sub
Private Sub downBtn_Click(sender As Object, e As EventArgs) Handles downBtn.Click
MoveDownDataRow(StepDGV.CurrentRow.Index)
End Sub
Private Sub MoveDownDataRow(RowIndex As Integer)
Dim OriginalStepNumber As Integer
Dim dv As DataView = StepsData.DefaultView
OriginalStepNumber = CInt(StepDGV.Rows(RowIndex).Cells("StepIDLS").Value)
If RowIndex = dv.Count - 1 Then
exit Sub
Else
dv(RowIndex + 1).BeginEdit()
dv(RowIndex + 1)("StepIDLS") = OriginalStepNumber
dv(RowIndex + 1).EndEdit()
dv(RowIndex).BeginEdit()
dv(RowIndex)("StepIDLS") = OriginalStepNumber + 1
dv(RowIndex).EndEdit()
End If
dv.Sort = "StepIDLS ASC"
' StepDGV.Rows(RowIndex).Selected = true
'StepDGV.Refresh()
'StepDGV.DataSource = StepsData
'StepDGV.Refresh()
StepDGV.ResetBindings()
StepDGV.Refresh()
End Sub[![screenshot of datagridview for visual aid when going through code][1]][1]
Since you have a sorted DataView, setting two consecutive values using the same Index reference, may (will) have undefined results, even more if you move in two different directions.
Method 1:
It's simpler (and functional) to get the reference of both DataRows from the current DataView and then change the value of a Column using the DataRow reference: even if the DataRow position in the sorted DataView changes, the DataRow reference is the same.
You don't need to BeginEdit/EndEdit a Cell value, these changes are propagated automatically.
► Here, I'm using the same Button.Click
handler for both Buttons and determine the direction based on the Button name (it could be anything else that fits).
► This line: Dim dView = DirectCast(StepDGV.DataSource, DataTable).DefaultView
is not necessary if you have stored a DataTable object (as it looks like).
If that's the case, of course use the DataTable reference you already have.
► It's assumed you have set StepsData.DefaultView.Sort = "StepIDLS ASC"
before this point.
Private Sub btnMoveRowUpDown_Click(sender As Object, e As EventArgs) Handles UpBtn.Click, downBtn.Click
If StepDGV.CurrentRow Is Nothing Then Return
Dim moveUp As Boolean = DirectCast(sender, Button).Name.Equals("UpBtn")
Dim currentRow As Integer = StepDGV.CurrentCell.RowIndex
Dim dView = DirectCast(StepDGV.DataSource, DataTable).DefaultView
Dim rowCurrent = dView(currentRow).Row
Dim colCurrentValue As Integer = CType(rowCurrent("StepIDLS"), Integer)
If moveUp Then
If currentRow = 0 Then Return
Dim rowPrevious = dView(currentRow - 1).Row
Dim colPreviousValue As Integer = CType(rowPrevious("StepIDLS"), Integer)
rowCurrent("StepIDLS") = colPreviousValue
rowPrevious("StepIDLS") = colCurrentValue
Else
If currentRow = StepDGV.NewRowIndex - 1 Then Return
Dim rowNext = dView(currentRow + 1).Row
Dim colNextValue As Integer = CType(rowNext("StepIDLS"), Integer)
rowCurrent("StepIDLS") = colNextValue
rowNext("StepIDLS") = colCurrentValue
End If
End Sub
Method 2:
You can do something similar setting the DataGridView Cells values.
In this case, you do need to call DataGridView.EndEdit() to notify the change, so it occurs immediately. Otherwise, the value change would be propagated after the focus leaves the CurrentCell
.
The notes here: Bound DataGridView not updating to display information + sorting issues may also be useful in a similar condition (when you have to directly set DataGridView Cells).
You can also notice that setting a DataRow Colums value also changes the DataGridView CurrentRow
(not just the CurrentCell
), while setting the Value of a Cell in a DataGridView, doesn't cause the CurrentRow
to change, so you have to do it yourself, setting:
[DataGridView].CurrentCell = [DataGridView].Rows(currentRow + 1).Cells(currentColumn)
Private Sub btnMoveRowUpDown_Click(sender As Object, e As EventArgs) Handles UpBtn.Click, downBtn.Click
If StepDGV.CurrentRow Is Nothing Then Return
Dim moveUp As Boolean = DirectCast(sender, Button).Name.Equals("UpBtn")
Dim currentRow As Integer = StepDGV.CurrentCell.RowIndex
Dim currentColumn As Integer = StepDGV.CurrentCell.ColumnIndex
Dim currentCellValue As Integer = CType(StepDGV("StepIDLS", currentRow).Value, Integer)
If moveUp Then
If currentRow = 0 Then Return
Dim previousCellValue As Integer = CType(StepDGV("StepIDLS", currentRow - 1).Value, Integer)
StepDGV.Rows(currentRow).Cells("StepIDLS").Value = previousCellValue
StepDGV.EndEdit()
StepDGV.Rows(currentRow - 1).Cells("StepIDLS").Value = currentCellValue
StepDGV.EndEdit()
StepDGV.CurrentCell = StepDGV.Rows(currentRow - 1).Cells(currentColumn)
Else
If currentRow = StepDGV.NewRowIndex - 1 Then Return
Dim nextCellValue As Integer = CType(StepDGV("StepIDLS", currentRow + 1).Value, Integer)
StepDGV.Rows(currentRow).Cells("StepIDLS").Value = nextCellValue
StepDGV.EndEdit()
StepDGV.Rows(currentRow + 1).Cells("StepIDLS").Value = currentCellValue
StepDGV.EndEdit()
StepDGV.CurrentCell = StepDGV.Rows(currentRow + 1).Cells(currentColumn)
End If
End Sub