如何通过 DataGridView 行连续循环?

How to cycle continuously through DataGridView rows?

这似乎是一个重复的问题,但我正在寻找一个特定的函数。我在 Whosebug 和 Google 上查看了类似的问题,并尝试使用许多不同的代码示例,但到目前为止,都没有成功?

我在做什么:

  1. 在运行时,即 Form1_Load,我调用一个函数在 DataGridView 中显示“MyFolder”中所有文件的文件信息。
  2. 我使用 Next/Previous 按钮循环浏览 DGV 行。

我的代码:

Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
    'Call Function To Display File Info From MyFolder:
    DataGridView1.DataSource = Fileinfo_To_DataTable("C:\Users\" + username + "\Documents\MyApp\MyFolder")
End Sub

'Next Button:
Private Sub btnNext_Click(sender As Object, e As EventArgs) Handles btnNext.Click

    If DataGridView1.SelectedRows(0).Index < DataGridView1.RowCount - 1 Then
        MyDesiredIndex = DataGridView1.SelectedRows(0).Index + 1
    Else
        MyDesiredIndex = 0
    End If

    DataGridView1.ClearSelection()
    DataGridView1.CurrentCell = DataGridView1.Rows(MyDesiredIndex).Cells(0)
    DataGridView1.Rows(MyDesiredIndex).Selected = True
End Sub

'Previous Button:  
Private Sub btnPrev_Click(sender As Object, e As EventArgs) Handles btnPrev.Click
    If DataGridView1.CurrentCell.RowIndex >= 0 And DataGridView1.CurrentCell.RowIndex <= DataGridView1.Rows.Count - 1 Then
        For Each row As DataGridViewRow In DataGridView1.Rows
            If Not row.IsNewRow Or vbNull Then
                MyDesiredIndex = DataGridView1.SelectedRows(0).Index - 1
            End If
        Next
    End If

    DataGridView1.ClearSelection()
    DataGridView1.CurrentCell = DataGridView1.Rows(MyDesiredIndex).Cells(0)
    DataGridView1.Rows(MyDesiredIndex).Selected = True
End Sub

问题:
Next 按钮在“连续循环”中无一例外地循环所有 DGV 行。 “连续循环”是指我的程序在第一行 (0) 或最后一行不停地循环遍历所有行(即,只要我继续按下下一步按钮,就会发生循环)。

Previous 按钮仅在我首先使用 Next 按钮更改所选行(即 First > Last)时才有效。然后,点击 Previous 按钮将所选行更改为第一行(即 Last > First)。但是,当程序到达第一行时,它抛出如下异常:

"System.ArgumentOutOfRangeException: 'Index was out of range. Must be non-negative and less than the size of the collection. Parameter name: index'"

  1. 解决超出范围异常。
  2. 解决cycling/looping遍历所有行的问题?

我试过的:
除了我上面的尝试(以及许多其他尝试),我在 Whosebug 上发现了以下代码,它解决了同样的问题,但它也在第一行停止而不循环遍历所有行:

移动到数据网格视图中的上一行
Moving to previous row in datagridview

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    Dim i As Integer = DataGridView1.CurrentRow.Index - 1
    If i < 0 Then i = 0
    DataGridView1.CurrentCell = Me.DataGridView1.Rows(i).Cells(0)
    DataGridView1.Rows(i).Selected = True
End Sub

期望的行为:
我将不胜感激任何帮助使 Previous 按钮的行为与 Next 按钮相同的方式,即连续循环所有行而不抛出异常。

我曾多次尝试寻找逻辑来“包含”范围内先前行的选择,但没有成功。但是,我真的很喜欢 Next 按钮不间断地连续循环遍历行的方式,并且想将此行为复制到 Previous 按钮以便能够不间断地连续双向循环(即 Next/Previous)?我也尝试了几种不同的 For Each 循环,但无法让代码以所需的方式工作?

有人知道我该如何实现吗?

使用 BindingSource as mediator between your data source of FileInfo objects and the DataGridView, you can directly make use of the BindingSource, MovePrevious(), MoveNext(), MoveFirst() and MoveLast() 方法。

请注意,所有这些都是void方法(Sub),none returns一个状态,但是你可以使用 Position 属性.

确定数据源中的当前位置
  • 使用 Environment.GetFolderPath() method to get the path of Special Folders as the current User's Documents folder. The Environment.SpecialFolder 枚举用于引用这些路径之一。
  • 始终使用 Path.Combine() 构建路径。
  • 将 BindingSource 对象声明为 Field,以便您以后可以轻松访问它。
  • OnLoad() 方法覆盖(或 Form.Load 事件处理程序,如您所愿)中,创建 FileInfo 对象的集合,将此集合设置为 BindingSource 的 DataSource 和将 BindingSource 作为 DataGridView 的数据源:
Private fileListSource As BindingSource = Nothing

Protected Overrides Sub OnLoad(e As EventArgs)
    MyBase.OnLoad(e)

    Dim docsPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)
    Dim filesPath = Path.Combine(docsPath, "MyApp\MyFolder")
    fileListSource = New BindingSource(New DirectoryInfo(filesPath).GetFiles("*.txt"), Nothing)
    DataGridView1.DataSource = fileListSource
End Sub

现在,您可以使用四个按钮来移动 Current 对象(另见 CurrencyManager class),使用 BindingSource 的上述方法,检查 Current 对象的位置,以确定在单击“下一个”或“上一个”按钮时是否必须 Current 移动到第一个或最后一个对象:

Private Sub btnMoveFirst_Click(sender As Object, e As EventArgs) Handles btnMoveFirst.Click
    fileListSource.MoveFirst()
End Sub

Private Sub btnMoveLast_Click(sender As Object, e As EventArgs) Handles btnMoveLast.Click
    fileListSource.MoveLast()
End Sub

Private Sub btnMovePrevious_Click(sender As Object, e As EventArgs) Handles btnMovePrevious.Click
    If fileListSource.Position > 0 Then
        fileListSource.MovePrevious()
    Else
        fileListSource.MoveLast()
    End If

End Sub

Private Sub btnMoveNext_Click(sender As Object, e As EventArgs) Handles btnMoveNext.Click
    If fileListSource.Position < fileListSource.Count - 1 Then
        fileListSource.MoveNext()            
    Else
        fileListSource.MoveFirst()
    End If
End Sub

它是这样工作的:
这里是未过滤的文件列表

使用 DataBinding,您可以将其他控件绑定到 BindingSource 并与其数据源交互,在本例中为 FileInfo 对象的集合。
这意味着当您更改绑定控件的 属性 值时,集合中当前对象的属性也会更改。
由于您有 FileInfo 对象,这会自动反映在基础 File 对象上,从而更改其属性。
这里,ReadOnlyCreationTimeLastWriteTime 使用一个 CheckBox 和两个 DateTimePickers 进行更改。

dtpLastWrite.DataBindings.Add("Value", fileListSource, "LastWriteTime", True, DataSourceUpdateMode.OnPropertyChanged)
dtpCreationTime.DataBindings.Add("Value", fileListSource, "CreationTime", False, DataSourceUpdateMode.OnPropertyChanged)
chkReadOnly.DataBindings.Add("Checked", fileListSource, "IsReadOnly", False, DataSourceUpdateMode.OnPropertyChanged)