向上或向下移动具有多重选择的复杂DataGridView行 [英] Move up or down little complex DataGridView rows with multi-selection

查看:129
本文介绍了向上或向下移动具有多重选择的复杂DataGridView行的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个这样的DataGridView:





现在,在 C#或其他 VB.Net 中,喜欢上下移动一个位置选定的行,我该怎么办?多选择要求使我复杂化。



将DataGridView中显示的文件合并为一个可执行文件,然后按照以下顺序执行文件: 订单列,因此在上下移动行时,订单值不可用。



我没有使用任何数据源。






我试图从 MSDN ,它包含一些扩展方法,但它需要一个datatable和datasource,我没有任何dissapoint使用datatable和数据源,但我不知道如何适应我的DataGridView的代码示例。
反正样本不支持多选:



上下移动行,记住DataGridView和ListBoxs数据绑定的顺序


$ b $我也在StackOverflow上看到有关C#的一些问题,但是他们要求单行选择:



如何在KeyUp或Keydown上上下移动gridview选定的行按



DataGridView所选行向上移动



然后,我没有起点,只是这些移动也不保存订单值的单行的方法,如果有人可以指导我o扩展我的需要的功能:
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

如果(dgv.SelectedCells.Count> 0)AndAlso(newRowIndex> = 0)然后

与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

如果(dgv.SelectedCells.Count> 0)AndAlso(dgv.Rows.Count> newRowIndex)然后

使用dgv
.Rows.Remove(curRow)
.Rows.Insert(newRowIndex,curRow)
.CurrentCell = dgv(curColIndex,newRowIndex)
结束

如果

End Sub







更新


我正在尝试@Plutonix方法(有一点修改),唯一的问题是它不能正确移动所选行到UP方向。



解决问题的步骤:


  1. 选择两行在一起(例如行索引2和行索引3,NOT行索引2和行索引4)


  2. 尝试将行移动到UP方向。


我可以如何解决?

  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

'行索引
Dim thisRow As DataGridViewRow

'将选择返回
Dim selectedRows As New List(Of Integer)

'最大行
Dim lastRowIndex As Integer =
如果(dgv.AllowUserToAddRows,
rows.Count - 2,
rows.Count - 1)



对于n As Integer = lastRowIndex到0 Step -1

如果不是行(n ).IsNewRow然后

如果行(n).Selected然后

selectedRows.Add(n)

MsgBox(n)

选择案例moveDirection

案例Main.MoveDirection.Down
如果((n + moveDirection)< = lastRowIndex)AndAlso n + moveDirection> = 0)AndAlso rows(n + moveDirection).Selected = False然后

selectedRows(selectedRows.Count - 1)=(n + moveDirection)
thisRow = rows n)
rows.Remove(thisRow)

rows.Insert(n + moveDirection,thisRow)

结束如果

案例主.MoveDirection.Up

如果((n + moveDirection)< = lastRowIndex)然后

MsgBox(selectedRows(selectedRows.Count - 1))
selectedRows selectedRows.Count - 1)=(n + moveDirection)
thisRow = rows(n)
rows.Remove(thisRow)

rows.Insert(n + moveDirection,thisRow)

如果

结束选择

结束如果

结束如果

下一个n

'重新选择原来的选定行
对于n As Integer = 0 to lastRowIndex

dgv.Rows(n).Selected = selectedRows.Contains(n)

'重新编号顺序(可选&未知,但琐碎)
dgv.Rows(n).Cells(0).Value =(n + 1)

下一个n

End Sub


解决方案

(更新)

您需要迭代行集合,测试是否选择每个集合,然后交换行。为了保持2个选定的行互相交换,当它们到达顶部或底部时,需要单独的Up和Down方法。

 '所选行的哈希码列表
私有函数GetSelectedRows()作为列表(整数)
Dim selR As新列表(整数)

'必须清除所选的NEXT行
'不会导致奇怪的行为
对于n As Integer = 0到dgv.Rows.Count - 1
如果dgv.Rows(n).IsNewRow = False AndAlso dgv.Rows(n).Selected Then
selR.Add(dgv.Rows(n).GetHashCode)
dgv.Rows( n).Selected = False
如果
下一个
返回selR
结束函数

'还原原始选定行
Private Sub SetSelectedRows selRows As List(Of Integer))

对于n As Integer = 0到dgv.Rows.Count - 1
如果dgv.Rows(n).IsNewRow = False然后
dgv.Ro ws(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
'行索引
Dim thisRow As DataGridViewRow
'put selection back
Dim selectedRows As List(Of Integer)
'最大行
Dim LastRow = If dgv.AllowUserToAddRows,rows.Count - 2,rows.Count - 1)

selectedRows = GetSelectedRows()

对于n As Int32 = 0 To LastRow
如果行(n).IsNewRow = False然后

如果(selectedRows.Contains(rows(n).GetHashCode))AndAlso(n - 1> = 0)AndAlso
(selectedRows.Contains (行(n-1).GetHashCode)= False)然后

thisRow = rows(n)
rows.Remove(thisRow)
rows.Inse rt(n-1,thisRow)
如果
结束If
下一个

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 =如果(dgv.AllowUserToAddRows,rows.Count - 2,rows.Count - 1)

selectedRows = GetSelectedRows()

对于n As Int32 = LastRow到0 Step -1

如果行(n).IsNewRow = False然后
如果(selectedRows.Contains(rows(n).GetHashCode))AndAlso(n + 1 <= LastRow)AndAlso
(selectedRows.Contains(rows(n + 1).GetHashCode)= False)然后
thisRow = rows(n)
rows.Remove(thisRow)
rows.Insert(n + 1 ,thisRow)
结束如果
结束如果
下一个

SetSelectedRows(selectedRows)

E nd sub

用法:

  MoveRowsUp()
'向下移动:
MoveRowsDn()

移动行会导致dgv重置选择。方法首先通过并获取所选行的HashCodes列表,然后根据该结果重置每个 Row.Selected 属性。



代码更改单元格(0)的值,以便顺序和顺序列匹配(这意味着Order列值 可变)。



如果还选择了目的地的行,则移动检查以查看此行是否位于结尾 OR 。这样可以防止行在顶部或底部进行交换。



之前:



之后:



请注意,当Zalgo到底3和5选择),另一个仍然可以向下移动,所以在Ziggy停留的时候。 Ziggy(3)向下移动的能力是基于下一行/索引(仅) - 下一行不超出底部 AND 未选中,因此它仍然可以向下移动1,而Zalgo(5)不能。


I have a DataGridView like this:

Now, In C# or else VB.Net, with a button, I would like to move up or down one position the selected rows, how I could do it?. The multi selection requisite complicate me this.

The files that appear in the DataGridView will be combined into a single executable file, then, the files will be executed in the order of the "Order" column, so the "Order" value should be inmutable when moving rows up or down.

I'm not using any data source.


I've tried to analyze this sample from MSDN, it consists in some extension methods, but it takes a datatable and datasource, I don't have any dissapoint to use a datatable and datasource but just I don't know how to adapt the code-sample for my DataGridView. Anyways the sample does not support multi selection:

Move rows up/down and remember order for DataGridView and ListBoxs data bound

I also have seen some C# questions about this on StackOverflow but they asks for single row selection:

How to move gridview selected row up/down on KeyUp or Keydown press

DataGridView Selected Row Move UP and DOWN

Then, I don't have an starting point, just these methods to move a SINGLE row that also does not preserve the Order value, if someone could guide me to extend the functionality for my needs: Private Sub Button_MoveUp_Click(sender As Object, e As EventArgs) _ Handles 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

I'm trying @Plutonix approach (with a little modification), the only problem is that it does not move properly the selected rows to UP direction.

Steps to reprduce the issue:

  1. Select two rows that are together (eg. row index 2 and row index 3, NOT row index 2 and row index 4)

  2. Try to move the rows to UP direction.

How I could fix it?.

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

解决方案

(Updated)
You need to iterate the rows collection, test if each is selected, then swap rows. In order to keep 2 selected rows from swapping with each other when they get to the top or bottom, a separate Up and Down method are needed.

' 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

Usage:

 MoveRowsUp()
 ' move down:
 MoveRowsDn()

Moving the rows causes the dgv to reset the selections. The methods first go thru and get a list of the HashCodes of the selected rows, then at the end resets each Row.Selected property based on that.

The code changes the value of Cell(0) so the order and Order column match (which means the Order column value is mutable).

Moving checks to see both if this row is at the end OR if the row at the destination is also selected. This prevents rows from swapping places when they get to the top or bottom.

Before:

After:

Note that when "Zalgo" got to the bottom (meaning 3 and 5 were selected), the other one could still move down one, so it did while "Ziggy" stayed put. The ability of "Ziggy(3)" to move down or not is based on the next row/index (only) - the next row is not beyond the bottom AND not selected so it can still move down 1, while "Zalgo (5)" could not.

这篇关于向上或向下移动具有多重选择的复杂DataGridView行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆