在 DataGridView 中按 ctrl F

ctrl F in DataGridView

我正在尝试在我的项目中实现与 ctrl+F 功能等效的功能。我希望它像在 excel 中一样工作,其中光标指向任何单元格中的匹配字符串。它还可以用作过滤器,只显示具有匹配字符串的行。

编辑 1:这是我在使用@Gabriel Stancu 的方法时尝试的方法:

        Private Sub btnSearch_Click(sender As Object, e As EventArgs) Handles btnSearch.Click
        'Dim search As New OleDbCommand
        'Dim da As OleDbDataAdapter
        Dim ds As New DataSet
        Dim dt As New DataTable
        Dim dgv As DataGridView

        Dim searchedValue As String
        frmPrinc.dgv.DataSource = dt.DefaultView

        searchedValue = txtBoxName.Text
        MsgBox(searchedValue) 'Displayed
        For Each row As DataGridViewRow In frmPrinc.dgv.Rows 
            MsgBox("yes") 'Not displayed
            For Each cell As DataGridViewCell In row.Cells
                MsgBox("yes2") 'Not displayed
                If cell.Value IsNot DBNull.Value Then
                    MsgBox("yes3") 'Not displayed
                    If cell.Value.ToString().Equals(searchedValue) Then
                        cell.Selected = True
                        MsgBox(cell.Selected)
                        Exit Sub
                    End If
                End If
            Next
        Next

    End Sub

这刚刚清除了我的 DataGridView 显示

编辑 2:这是我目前正在使用@jmcilhinney 的方法进行的工作:

    Private Sub btnSearch_Click(ByVal sender As Object, ByVal e As EventArgs) Handles btnSearch.Click

        Dim myBindingSource As New BindingSource
        Dim myDataTable As New DataTable
        Dim myDataGridView As New DataGridView
        myBindingSource.DataSource = myDataTable
        myDataGridView.DataSource = myBindingSource

        Dim myValue As String

        myValue = txtBoxName.Text
        
        MsgBox(myValue)
        myDataTable.Columns.Add(New DataColumn("NAME", GetType(String)))
        myBindingSource.DataSource = myDataTable

        myBindingSource.Position = myBindingSource.Find("NAME", myValue) 'Running fails on this line


        'myBindingSource.Filter = $"MyColumn LIKE '%{myValue}% OR MyOtherColumn LIKE '%{myValue}%'"

        Dim sourceRows = myBindingSource.Cast(Of DataRowView)().
                                 Where(Function(drv) CStr(drv("NOM")).Contains(myValue)).
                                 ToArray()

        For Each gridRow As DataGridViewRow In myDataGridView.Rows
            gridRow.Selected = sourceRows.Contains(DirectCast(gridRow.DataBoundItem, DataRowView))
        Next

    End Sub

以上内容仍在进行中,但我有点卡住了

System.ArgumentException : 'DataMember property' NAME 'could not be found in the DataSource.'

正如评论中jmcilhinney指出的那样,您的代码与您要实现的目标无关。我想到的第一种方法(可能不是最有效的)是逐行逐列进行。类似于:

    Private Sub SearchCellValue(ByVal searchedValue As String)
        For Each row As DataGridViewRow In dgvSample.Rows
            For Each cell As DataGridViewCell In row.Cells
                If cell.Value IsNot DBNull.Value And cell.Value IsNot Nothing Then 'you also need to check for the "Nothing" value
                    If cell.Value.ToString().Equals(searchedValue) Then
                        dgvSample.SelectionMode = DataGridViewSelectionMode.CellSelect 'add this to only select a cell, not the entire row
                        cell.Selected = True
                        Exit Sub
                    End If
                End If
            Next
        Next
    End Sub

您还可以在保存 DataGridView 数据的 DataTable 中搜索,获取相应的索引(行和列)和然后 select DataGridView 中的相应单元格(因为直接在应该分开的 UI 上实现代码逻辑并不是最佳做法)。无论如何,这两种方法似乎都比直接在数据库中查看更快,因为您的方法表明您打算这样做。

您还可以将其设为 布尔函数 和 return 一个值(True 如果您找到该值,False 否则)。这只是指导您的示例代码。在进入复杂的内容之前,请确保您阅读了一些文档或至少按照一些教程一步步进行。

如果您已经有一个填充的网格,那么搜索或过滤的代码与您的数据库没有任何关系。您应该做的是填充 DataTable,使用数据适配器或数据 reader,将其绑定到 BindingSource,然后将其绑定到您的 DataGridView,例如

myBindingSource.DataSource = myDataTable
myDataGridView.DataSource = myBindingSource

然后使用 BindingSource 进行搜索或过滤。至 select 特定列中具有特定值的第一条记录:

myBindingSource.Position = myBindingSource.Find("MyColumn", myValue)

过滤掉任何列中不包含部分值的行:

myBindingSource.Filter = $"MyColumn LIKE '%{myValue}% OR MyOtherColumn LIKE '%{myValue}%'"

至 select 网格中符合这些条件但未实际过滤的每一行:

Dim sourceRows = myBindingSource.Cast(Of DataRowView)().
                                 Where(Function(drv) CStr(drv("MyColumn")).Contains(myValue)).
                                 ToArray()

For Each gridRow As DataGridViewRow In myDataGridView.Rows
    gridRow.Selected = sourceRows.Contains(DirectCast(gridRow.DataBoundItem, DataRowView))
Next

好的,感谢@Gabriel Stancu 这对我有用:

    Private Sub btnSearch_Click(sender As Object, e As EventArgs) Handles btnSearch.Click
       
        Dim da As OleDbDataAdapter
        Dim ds As New DataSet
        Dim dt As New DataTable
        Dim dgv As New DataGridView

        ds.Tables.Add(dt)
        da = New OleDbDataAdapter("*", getConnexion) ' * here are my columns name
        Dim cmdBuilder As New OleDbCommandBuilder(da)
        cmdBuilder.QuotePrefix = "["
        cmdBuilder.QuoteSuffix = "]"
        da.Fill(dt) 'here is what i forgot
        dgv.DataSource = dt.DefaultView
        Dim searchedValue As String
        frmPrinc.dgv.DataSource = dt.DefaultView

        searchedValue = txtBoxName.Text
        'MsgBox(searchedValue) 'breakpoint to make sure the input string was correct
        For Each row As DataGridViewRow In frmPrinc.dgv.Rows
            For Each cell As DataGridViewCell In row.Cells
                If cell.Value IsNot DBNull.Value And cell.Value IsNot Nothing Then 'you also need to check for the "Nothing" value
                    If cell.Value.ToString().Equals(searchedValue) Then
                        frmPrinc.dgv.SelectionMode = DataGridViewSelectionMode.CellSelect 'add this to only select a cell, not the entire row
                        cell.Selected = True
                        Exit Sub
                    End If
                End If
            Next
        Next
    End Sub