Hi, using VB 2008, I have a datagridview bound to a datasource and want to position to a row based on the value keyed by the user in a textbox. I can sort of accomplish this with one line of code on the textbox changed event i.e.:
Me.BindingSource.Position = Me.BindingSource.Find("ColumnName", TextBox1.Text)
which works great when the user keys in an exact match. Question is, how do I position to a partial match, i.e. the first match found, i.e. "ABC " might position to "ABCDEFG" if it is the first record alphabetically. I can't seem to find a decent example of how to do this.
Thanks,
Bill P.

Dani AI

Generated

Quick summary: and correctly pointed out that a filter/LIKE will find substrings, but it changes the displayed set. showed a loop-based approach that keeps the full list but used a numeric padding trick. If you want to preserve every row and simply move the current position to the first partial match, a small, robust scan of the BindingSource is the cleanest solution — it avoids hiding rows and is easy to tune for prefix vs substring matching.

' position to first partial match without changing the visible set
Dim search As String = txtSearch.Text.Trim()
If String.IsNullOrEmpty(search) Then Exit Sub

For i As Integer = 0 To myBindingSource.Count - 1
    Dim item = myBindingSource(i)
    Dim value As String = String.Empty

    If TypeOf item Is DataRowView Then
        Dim drv As DataRowView = CType(item, DataRowView)
        value = If(drv.Row.IsNull(columnName), String.Empty, drv(columnName).ToString())
    Else
        Dim prop = item.GetType().GetProperty(columnName)
        If prop IsNot Nothing Then
            Dim v = prop.GetValue(item, Nothing)
            value = If(v Is Nothing, String.Empty, v.ToString())
        End If
    End If

    ' prefix match; use IndexOf(..., StringComparison.OrdinalIgnoreCase) >= 0 for substring anywhere
    If value.StartsWith(search, StringComparison.OrdinalIgnoreCase) Then
        myBindingSource.Position = i
        If myGrid.Rows.Count > i Then myGrid.FirstDisplayedScrollingRowIndex = i
        Exit For
    End If
Next

Notes and tips: handle DBNull and null property values as shown; use StartsWith for a prefix search or IndexOf for "contains". For very large data sets consider an indexed search (DataView or DataTable.Select) or a binary search when the source is sorted to avoid O(n) scans. When wiring this to TextChanged, debounce the handler (a short Timer) so you do not scan on every keystroke. This approach preserves the full DataGridView (no filtering), is culture- and case-aware when you use the proper StringComparison, and is more predictable than padding tricks.

Recommended Answers

All 6 Replies

I worked on something like this a little while ago, we used the filter & sort propery to narrow down the list.

Me.BindingSource.Filter = "Column LIKE '" & Textbox.Text & "&'"
And
Me.BindingSource.Sort = "Column Desc"

I think it's
Me.BindingSource.Filter = "Column LIKE '%" & Textbox.Text & "%'"

I think it's
Me.BindingSource.Filter = "Column LIKE '%" & Textbox.Text & "%'"

Opps, A typo on my part...:$

I wasn't sure, but I thought it was worth mentioning just in case:)

Thanks, this looks like it will work. In the interim, I have another solution which I came up with and will stick with in this case, as if it ain't broke, etc...
What I did was loop through the rows programattically and see if the first cell contents was in the range of what the user typed in the textbox field with a whole bunch of 99999's concatenated to it, with the result of positioning the datagridview at the first row that matched that fell in that range. It seems kind of a hokey way to do it, but it preserves the datagridview list as a whole where I think the filter approach would present a subset of the list, which I don't really want.

Dim i As Integer ' index for loop
        Dim r As Integer ' for retrieve row count 
        Dim UpperLimitString As String ' upper range limit
        Dim cellvalue As String ' cell value retrieved
        UpperLimitString = CStr(TextBox1.Text + "99999") ' set upper limit
        r = DoctorsDataGridView.RowCount ' get row count
        r = r - 2 ' adjust for 0 index and blank row at bottom

        For i = 0 To r 'loop through all rows 

            cellvalue = ""
            cellvalue = CStr(DoctorsDataGridView(0, i).Value)

            ' 1st cell value within range of keyed value & upper limit?
            If CStr(cellvalue.ToString) >= (CStr(TextBox1.Text)) And (CStr(TextBox1.Text) <= CStr(UpperLimitString.ToString)) Then
                Me.DoctorsBindingSource.Position = Me.DoctorsBindingSource.Find("Doctor", cellvalue)
                GoTo GotMyRecord
            End If
        Next i
        Me.DoctorsBindingSource.Position = Me.DoctorsBindingSource.Find("Doctor", cellvalue)
        End

GotMyRecord:

Thanks for your help. I'm putting both methods in my toolbox.
Bill P.

In playing around, I tried filter with a wildcard on a new textbox field and it works great:

Private Sub TextBox2_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TextBox2.TextChanged

        DoctorsBindingSource.Filter = "Doctor like '%" + TextBox2.Text + "%'"

End Sub
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.