【问题标题】:ctrl F in DataGridViewDataGridView 中的 ctrl F
【发布时间】:2020-07-27 07:38:33
【问题描述】:

我正在尝试在我的项目中实现与 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.'

【问题讨论】:

  • 根据您实际描述的内容,该代码绝对没有意义。一方面,如果您尝试执行查询,为什么要调用ExecuteNonQuery?如果您尝试在 DataGridView 中实现 Find 函数,那么这意味着您已经拥有一个填充的 DataGridView,但情况似乎并非如此,因此您应该学习首先如何做到这一点。首先了解如何执行查询,然后了解如何使用该查询的结果填充DataGridView。完成这两件事后,也许您可​​以考虑在本地搜索该数据。
  • 对不起,如果我没有说清楚,但是是的,我刚刚开始学习,我已经有一个填充的 DataGridView,我只是强调我尝试过的内容,我明白这没有任何意义.这就是为什么我要寻求帮助才能做到这一点。

标签: vb.net search filter datagridview ms-access-2003


【解决方案1】:

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

myBindingSource.DataSource = myDataTable
myDataGridView.DataSource = myBindingSource

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

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

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

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

在网格中选择与这些条件匹配的每一行而不进行实际过滤:

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

【讨论】:

  • 我不确定“MyColumn”和“myOtherColumn”指的是什么。我什么时候申报?
  • 您不会在任何地方声明它们。它们是您的DataTable 中列的名称,几乎可以肯定与您的数据库列相同。
【解决方案2】:

好的,感谢@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

【讨论】:

    【解决方案3】:

    正如在 cmets 中指定的 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中搜索,获取相应的索引(行和列),然后在DataGridView(因为直接在应该分开的 UI 上实现代码逻辑并不是最佳实践)。无论如何,这两种方法似乎都比直接在数据库中查找要快,正如您的方法所建议的那样。

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

    【讨论】:

    • 我试图在我的混乱中测试你的代码,但它不想进入For 循环。这很奇怪。
    • 你这是什么意思?您是否尝试过使用调试工具来查看原因?例如,一步一步地检查 datagridview 是否有行(它应该有,你可以在 UI 中看到)。您确定首先调用了 find 方法吗?当您尝试在网格中查找值时,放置一个断点并检查应用程序的工作流程。您究竟是如何从用户输入中捕获“Ctrl+F”命令的?
    • 我确实在每一步都设置了断点(当它获取字符串时,当它进入行、单元格等时)。它告诉我它得到了正确的字符串,但没有别的。我从 Windows 窗体文本框中获取输入,然后按按钮进行搜索
    • 那么它会遍历行和列吗?
    • 不,因为它仅在For 循环启动时才开始,但我可能知道它为什么不起作用,稍后我会及时通知您,我很快就会吃饭
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-12-21
    • 2014-01-29
    • 1970-01-01
    • 2013-06-11
    • 1970-01-01
    • 2012-11-24
    • 2018-10-26
    相关资源
    最近更新 更多