在排序的 DataTable 中上下移动行作为 DataGridView 的数据源不会更新视图
Moving Rows up and down in a sorted DataTable set as the DataSource of a DataGridView does not update the View
我在网上看过很多类似内容的不同帖子。我的代码正确地移动了行。
这是发生了什么:我按下向上或向下按钮,selected 行相应地移动。
如果我单击刚刚移动的行并尝试将其移回,它会按 DataTable 的 DefaultView 排序顺序移动它,但位置更改不会反映在 DataGridView 中。
如果我 select 从未移动过的行,它会移动它并且 DataGridView 会反映它,但是如果我再次选择同一行并尝试将其移回,则此更改是未反映在视图中,但更新了 DataTable。
我已尝试 ResetBindings
、DataGridView.Refresh
、重置此作品的数据源:none。
任何人都知道为什么会发生这种情况以及我如何解决它以便每次都反映更改?
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]
由于您有一个排序的 DataView,使用相同的索引引用设置两个连续的值,可能(将会)有未定义的结果,如果您在两个不同的 方向 移动,甚至更多。
方法一:
从当前 DataView 中获取两个 DataRow 的引用然后使用 DataRow 引用更改 Column 的值更简单(并且更实用):即使排序后的 DataView 中的 DataRow 位置发生变化,DataRow 引用也是相同。
您不需要 BeginEdit/EndEdit 单元格值,这些更改会自动传播。
► 在这里,我对两个按钮使用相同的 Button.Click
处理程序,并根据按钮名称确定方向(可以是任何其他适合的名称)。
► 此行:Dim dView = DirectCast(StepDGV.DataSource, DataTable).DefaultView
如果您存储了 DataTable 对象(看起来像),则不需要。
如果是这种情况,当然可以使用您已有的 DataTable 引用。
► 假设您在此之前设置了StepsData.DefaultView.Sort = "StepIDLS ASC"
。
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
方法二:
您可以执行类似的设置 DataGridView 单元格值。
在这种情况下,您确实需要调用 DataGridView.EndEdit() to notify the change, so it occurs immediately. Otherwise, the value change would be propagated after the focus leaves the CurrentCell
。
此处的注意事项: 在类似情况下也可能有用(当您必须直接设置 DataGridView 单元格时)。
您还可以注意到,设置 DataRow Colums 值也会更改 DataGridView CurrentRow
(而不仅仅是 CurrentCell
),而在 DataGridView 中设置单元格的值不会导致CurrentRow
要改变,所以你必须自己做,设置:
[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
我在网上看过很多类似内容的不同帖子。我的代码正确地移动了行。
这是发生了什么:我按下向上或向下按钮,selected 行相应地移动。
如果我单击刚刚移动的行并尝试将其移回,它会按 DataTable 的 DefaultView 排序顺序移动它,但位置更改不会反映在 DataGridView 中。
如果我 select 从未移动过的行,它会移动它并且 DataGridView 会反映它,但是如果我再次选择同一行并尝试将其移回,则此更改是未反映在视图中,但更新了 DataTable。
我已尝试 ResetBindings
、DataGridView.Refresh
、重置此作品的数据源:none。
任何人都知道为什么会发生这种情况以及我如何解决它以便每次都反映更改?
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]
由于您有一个排序的 DataView,使用相同的索引引用设置两个连续的值,可能(将会)有未定义的结果,如果您在两个不同的 方向 移动,甚至更多。
方法一:
从当前 DataView 中获取两个 DataRow 的引用然后使用 DataRow 引用更改 Column 的值更简单(并且更实用):即使排序后的 DataView 中的 DataRow 位置发生变化,DataRow 引用也是相同。
您不需要 BeginEdit/EndEdit 单元格值,这些更改会自动传播。
► 在这里,我对两个按钮使用相同的 Button.Click
处理程序,并根据按钮名称确定方向(可以是任何其他适合的名称)。
► 此行:Dim dView = DirectCast(StepDGV.DataSource, DataTable).DefaultView
如果您存储了 DataTable 对象(看起来像),则不需要。
如果是这种情况,当然可以使用您已有的 DataTable 引用。
► 假设您在此之前设置了StepsData.DefaultView.Sort = "StepIDLS ASC"
。
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
方法二:
您可以执行类似的设置 DataGridView 单元格值。
在这种情况下,您确实需要调用 DataGridView.EndEdit() to notify the change, so it occurs immediately. Otherwise, the value change would be propagated after the focus leaves the CurrentCell
。
此处的注意事项:
您还可以注意到,设置 DataRow Colums 值也会更改 DataGridView CurrentRow
(而不仅仅是 CurrentCell
),而在 DataGridView 中设置单元格的值不会导致CurrentRow
要改变,所以你必须自己做,设置:
[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