我有一个像这样的 DataGridView:
现在,在 C# 或 VB.Net 中,我想通过一个按钮将所选行向上或向下移动一个位置,我该怎么做?。多重选择的要求使我变得复杂。
出现在DataGridView中的文件将合并为一个可执行文件,然后,这些文件将按照“Order”列的顺序执行,所以“Order "向上或向下移动行时,值应该是不可变的。
我没有使用任何数据源。
我已经尝试分析来自 MSDN 的这个示例,它包含一些扩展方法,但它需要一个数据表和数据源,我对使用数据表和数据源没有任何失望但是只是我不知道如何为我的 DataGridView 调整代码示例。 无论如何,示例不支持多选:
Move rows up/down and remember order for DataGridView and ListBoxs data bound
我还在 StackOverflow 上看到了一些关于此的 C# 问题,但他们要求选择单行:
How to move gridview selected row up/down on KeyUp or Keydown press
DataGridView Selected Row Move UP and DOWN
然后,我没有起点,只有这些方法来移动也不保留 Order 值的 SINGLE 行,如果有人可以指导我扩展我需要的功能: Private Sub Button_MoveUp_Click(sender As Object, e As EventArgs) _ 处理 Button_MoveUp.Click
Me.MoveUpSelectedRows(Me.DataGridView_Files)
End Sub
Private Sub Button_MoveDown_Click(sender As Object, e As EventArgs) _
Handles Button_MoveDown.Click
Me.MoveDownSelectedRows(Me.DataGridView_Files)
End Sub
Private Sub MoveUpSelectedRows(ByVal dgv As DataGridView)
Dim curRowIndex As Integer = dgv.CurrentCell.RowIndex
Dim newRowIndex As Integer = curRowIndex - 1
Dim curColIndex As Integer = dgv.CurrentCell.ColumnIndex
Dim curRow As DataGridViewRow = dgv.CurrentRow
If (dgv.SelectedCells.Count > 0) AndAlso (newRowIndex >= 0) Then
With dgv
.Rows.Remove(curRow)
.Rows.Insert(newRowIndex, curRow)
.CurrentCell = dgv(curColIndex, newRowIndex)
End With
End If
End Sub
Private Sub MoveDownSelectedRows(ByVal dgv As DataGridView)
Dim curRowIndex As Integer = dgv.CurrentCell.RowIndex
Dim newRowIndex As Integer = curRowIndex + 1
Dim curColIndex As Integer = dgv.CurrentCell.ColumnIndex
Dim curRow As DataGridViewRow = dgv.CurrentRow
If (dgv.SelectedCells.Count > 0) AndAlso (dgv.Rows.Count > newRowIndex) Then
With dgv
.Rows.Remove(curRow)
.Rows.Insert(newRowIndex, curRow)
.CurrentCell = dgv(curColIndex, newRowIndex)
End With
End If
End Sub
UPDATE
我正在尝试@Plutonix 方法(稍作修改),唯一的问题是它没有正确地将选定的行移动到向上方向。
重现问题的步骤:
选择在一起的两行(例如,行索引 2 和行索引 3,而不是行索引 2 和行索引 4)
尝试将行向上移动。
我该如何解决?
Public Enum MoveDirection As Integer
Up = -1
Down = 1
End Enum
Private Sub MoveRows(ByVal dgv As DataGridView, ByVal moveDirection As MoveDirection)
Dim rows As DataGridViewRowCollection = dgv.Rows
' row index
Dim thisRow As DataGridViewRow
' put selection back
Dim selectedRows As New List(Of Integer)
' max rows
Dim lastRowIndex As Integer =
If(dgv.AllowUserToAddRows,
rows.Count - 2,
rows.Count - 1)
For n As Integer = lastRowIndex To 0 Step -1
If Not rows(n).IsNewRow Then
If rows(n).Selected Then
selectedRows.Add(n)
MsgBox(n)
Select Case moveDirection
Case Main.MoveDirection.Down
If ((n + moveDirection) <= lastRowIndex) AndAlso (n + moveDirection >= 0) AndAlso rows(n + moveDirection).Selected = False Then
selectedRows(selectedRows.Count - 1) = (n + moveDirection)
thisRow = rows(n)
rows.Remove(thisRow)
rows.Insert(n + moveDirection, thisRow)
End If
Case Main.MoveDirection.Up
If ((n + moveDirection) <= lastRowIndex) Then
MsgBox(selectedRows(selectedRows.Count - 1))
selectedRows(selectedRows.Count - 1) = (n + moveDirection)
thisRow = rows(n)
rows.Remove(thisRow)
rows.Insert(n + moveDirection, thisRow)
End If
End Select
End If
End If
Next n
' reselect the original selected rows
For n As Integer = 0 To lastRowIndex
dgv.Rows(n).Selected = selectedRows.Contains(n)
' renumber the order (optional & unknown, but trivial)
dgv.Rows(n).Cells(0).Value = (n + 1)
Next n
End Sub
最佳答案
(更新)
您需要迭代行集合,测试是否每个都被选中,然后交换行。为了防止 2 个选定的行在到达顶部或底部时相互交换,需要一个单独的 Up 和 Down 方法。
' list of hash codes of the selected rows
Private Function GetSelectedRows() As List(Of Integer)
Dim selR As New List(Of Integer)
' have to clear selected so the NEXT row
' doesnt cause odd behavior
For n As Integer = 0 To dgv.Rows.Count - 1
If dgv.Rows(n).IsNewRow = False AndAlso dgv.Rows(n).Selected Then
selR.Add(dgv.Rows(n).GetHashCode)
dgv.Rows(n).Selected = False
End If
Next
Return selR
End Function
' restore original selected rows
Private Sub SetSelectedRows(selRows As List(Of Integer))
For n As Integer = 0 To dgv.Rows.Count - 1
If dgv.Rows(n).IsNewRow = False Then
dgv.Rows(n).Selected = selRows.Contains(dgv.Rows(n).GetHashCode)
' reset Order col:
dgv.Rows(n).Cells(0).Value = n + 1
End If
Next
End Sub
Private Sub MoveRowsUp()
' short ref
Dim rows As DataGridViewRowCollection = dgv.Rows
' row index
Dim thisRow As DataGridViewRow
' put selection back
Dim selectedRows As List(Of Integer)
' max rows
Dim LastRow = If(dgv.AllowUserToAddRows, rows.Count - 2, rows.Count - 1)
selectedRows = GetSelectedRows()
For n As Int32 = 0 To LastRow
If rows(n).IsNewRow = False Then
If (selectedRows.Contains(rows(n).GetHashCode)) AndAlso (n - 1 >= 0) AndAlso
(selectedRows.Contains(rows(n - 1).GetHashCode) = False) Then
thisRow = rows(n)
rows.Remove(thisRow)
rows.Insert(n - 1, thisRow)
End If
End If
Next
SetSelectedRows(selectedRows)
End Sub
Private Sub MoveRowsDn()
Dim rows As DataGridViewRowCollection = dgv.Rows
Dim thisRow As DataGridViewRow
Dim selectedRows As New List(Of Integer)
Dim LastRow = If(dgv.AllowUserToAddRows, rows.Count - 2, rows.Count - 1)
selectedRows = GetSelectedRows()
For n As Int32 = LastRow To 0 Step -1
If rows(n).IsNewRow = False Then
If (selectedRows.Contains(rows(n).GetHashCode)) AndAlso (n + 1 <= LastRow) AndAlso
(selectedRows.Contains(rows(n + 1).GetHashCode) = False) Then
thisRow = rows(n)
rows.Remove(thisRow)
rows.Insert(n + 1, thisRow)
End If
End If
Next
SetSelectedRows(selectedRows)
End Sub
用法:
MoveRowsUp()
' move down:
MoveRowsDn()
移动行会导致 dgv 重置选择。这些方法首先获取所选行的 HashCode 列表,然后在最后根据该列表重置每个 Row.Selected
属性。
代码更改 Cell(0) 的值,因此订单和订单列匹配(这意味着订单列值是可变的)。
如果此行位于末尾或如果目标行也被选中,则移动检查两者。这可以防止行在到达顶部或底部时交换位置。
之前:
之后:
请注意,当“Zalgo”到达底部(意味着选择了 3 和 5)时,另一个仍然可以向下移动一个,所以它会这样做,而“Ziggy”则留在原地。 “Ziggy(3)”是否向下移动的能力取决于下一行/索引(仅)- 下一行不超出底部 AND 未被选中,因此它仍然可以向下移动1,而“Zalgo (5)”则不能。
关于c# - 通过多选向上或向下移动复杂的 DataGridView 行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30832922/