2

这似乎是一个重复的问题,但我正在寻找一个特定的功能。我查看了 StackOverflow 和 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) 还是在最后一行(即,只要我继续按下 Next 按钮,就会发生循环)。

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

“System.ArgumentOutOfRangeException:'索引超出范围。必须为非负数且小于集合的大小。参数名称:索引'”

  1. 解决超出范围异常。
  2. 解决所有行的循环/循环问题?

我尝试过的:
除了我上面的尝试(和许多其他尝试)之外,我在 StackOverflow 上找到了以下代码,它解决了同样的问题,但它也停在第一行而不循环遍历所有行:

移至 datagridview
中的上一行 移至 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

期望的行为:
我将不胜感激任何帮助,以使上一个按钮的行为方式与下一个按钮的行为方式相同,即连续循环遍历所有行而不会引发异常。

我做了很多尝试来寻找逻辑来“包含”该范围内先前行的选择,但没有成功。但是,我真的很喜欢 Next 按钮在行中连续循环而不停止的方式,并且希望将此行为复制到 Previous 按钮,以便能够在不停止的情况下连续循环两种方式(即 Next/Previous)?我也尝试了几个不同的For Each循环,但无法让代码以所需的方式工作?

有谁知道我如何实现这一目标?

4

1 回答 1

4

使用BindingSource作为FileInfo 对象的数据源和 DataGridView 之间的中介,您可以直接使用 BindingSource、MovePrevious()MoveNext()、 MoveFirst ()MoveLast()方法。

请注意,所有这些都是void方法 ( Sub),没有一个返回state,但您可以使用Position属性确定数据源中的当前位置。

  • 使用Environment.GetFolderPath()方法获取特殊文件夹的路径作为当前用户的文档文件夹。Environment.SpecialFolder枚举用于引用这些路径之一。
  • 始终使用Path.Combine()来构建路径。
  • 将 BindingSource 对象声明为字段,以便您以后可以轻松访问它。
  • OnLoad()方法覆盖(或Form.Load您喜欢的事件处理程序)中,创建FileInfo对象集合,将此集合设置为 BindingSource 的 DataSource,并将 BindingSource 设置为 DataGridView 的 DataSource:
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类),使用前面提到的 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 对象上,从而更改其属性。
在这里,ReadOnlyCreationTime使用LastWriteTimeCheckBox 和两个 DateTimePicker 进行更改。

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)

BindingSource DataGridView MoveNext MovePrevious

于 2021-09-15T19:28:37.480 回答