search in DataGridView

StewartBW 885 Reputation points
2024-06-20T05:13:49.44+00:00

Hello experts

I need to select some DataGridView rows based on the user text input, some sort of search, so:

For loop As Integer = 0 To DataGridView.Rows.Count - 1
    If DataGridView.Item(0, loop).Value.ToString.ToLowerInvariant.Contains(SearchTextBoxDropDown.Text.ToLowerInvariant) = True Then
        DataGridView.Rows.Item(loop).Selected = True
    End If
Next

Then scroll to the first selected row:

Dim FirstRow As Integer = DataGridView.SelectedRows(0).Index
For loop2 As Integer = 0 To DataGridView.SelectedRows.Count - 1
    If DataGridView.SelectedRows(loop2).Index < FirstRow Then
        FirstRow = DataGridView.SelectedRows(loop2).Index
    End If
Next
DataGridView.FirstDisplayedScrollingRowIndex = FirstRow

This combination works, but is very slow when there are a large number of rows (the second part is slower)

Is there some implemented methods that can increase the performance and speed of such operation, or if not, am I doing something inefficiently?

Thanks for advise :)

VB
VB
An object-oriented programming language developed by Microsoft that is implemented on the .NET Framework. Previously known as Visual Basic .NET.
2,661 questions
0 comments No comments
{count} votes

Accepted answer
  1. Jiachen Li-MSFT 29,026 Reputation points Microsoft Vendor
    2024-06-20T06:45:45.68+00:00

    Hi @StewartBW ,

    You can use LINQ to make the code more concise and potentially more efficient.

    DataGridView.ClearSelection()
    
    Dim searchText As String = SearchTextBoxDropDown.Text.ToLowerInvariant()
    Dim matchingRows = (From row As DataGridViewRow In DataGridView.Rows
                        Where row.Cells(0).Value.ToString().ToLowerInvariant().Contains(searchText)
                        Select row.Index).ToList()
    
    For Each rowIndex As Integer In matchingRows
        DataGridView.Rows(rowIndex).Selected = True
    Next
    
    If matchingRows.Count > 0 Then
        DataGridView.FirstDisplayedScrollingRowIndex = matchingRows(0)
    End If
    
    

    Best Regards.

    Jiachen Li


    If the answer is helpful, please click "Accept Answer" and upvote it.

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    1 person found this answer helpful.

2 additional answers

Sort by: Most helpful
  1. Deleted

    This answer has been deleted due to a violation of our Code of Conduct. The answer was manually reported or identified through automated detection before action was taken. Please refer to our Code of Conduct for more information.


    Comments have been turned off. Learn more

  2. KOZ6.0 6,300 Reputation points
    2024-06-20T09:24:27.1366667+00:00

    Using a BindingList<T> as the DataSource for element lookup is fast

    Imports System.ComponentModel
    
    Public Class Form1
    
        Class Item
            Implements INotifyPropertyChanged
    
            Private _Name As String
    
            Public Property Name As String
                Get
                    Return _Name
                End Get
                Set(value As String)
                    If (value Is Nothing) Then
                        _Name = String.Empty
                        LowerInvariant = String.Empty
                    Else
                        _Name = value
                        LowerInvariant = value.ToLowerInvariant()
                    End If
                    OnPropertyChanged(NameOf(Name))
                End Set
            End Property
    
            Public LowerInvariant As String
    
            Protected Overridable Sub OnPropertyChanged(propertyName As String)
                RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propertyName))
            End Sub
    
            Public Event PropertyChanged As PropertyChangedEventHandler _
                    Implements INotifyPropertyChanged.PropertyChanged
        End Class
    
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            DataGridView1.AllowUserToAddRows = False
            Dim list As New BindingList(Of Item)()
            For i As Integer = 1 To 10000
                list.Add(New Item With {.Name = GenerateRandomString()})
            Next
            DataGridView1.DataSource = list
        End Sub
    
        Dim random As New Random()
    
        Function GenerateRandomString() As String
            Dim length As Integer = GetRandomNumber(10, 15)
            Dim chars As String = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
            Dim stringChars(length - 1) As Char
            For i As Integer = 0 To stringChars.Length - 1
                stringChars(i) = chars(Random.Next(chars.Length))
            Next
            Return New String(stringChars)
        End Function
    
        Function GetRandomNumber(min As Integer, max As Integer) As Integer
            Dim random As New Random()
            Return random.Next(min, max + 1)
        End Function
    
        Sub Search1()
            DataGridView1.ClearSelection()
            Dim searchText As String = SearchTextBoxDropDown.Text.ToLowerInvariant()
            Dim firstRowIndex As Integer = -1
            For i As Integer = 0 To DataGridView1.Rows.Count - 1
                If DataGridView1.Item(0, i).Value.ToString.ToLowerInvariant.Contains(searchText) = True Then
                    DataGridView1.Rows.Item(i).Selected = True
                    If firstRowIndex = -1 Then
                        firstRowIndex = i
                    End If
                End If
            Next
            If firstRowIndex <> -1 Then
                DataGridView1.FirstDisplayedScrollingRowIndex = firstRowIndex
            End If
        End Sub
    
        Sub Search2()
            DataGridView1.ClearSelection()
            Dim list As BindingList(Of Item) = DirectCast(DataGridView1.DataSource, BindingList(Of Item))
            Dim searchText As String = SearchTextBoxDropDown.Text.ToLowerInvariant()
            Dim firstRowIndex As Integer = -1
            For i As Integer = 0 To list.Count - 1
                If list(i).Name.ToLowerInvariant().Contains(searchText) Then
                    DataGridView1.Rows.Item(i).Selected = True
                    If firstRowIndex = -1 Then
                        firstRowIndex = i
                    End If
                End If
            Next
            If firstRowIndex <> -1 Then
                DataGridView1.FirstDisplayedScrollingRowIndex = firstRowIndex
            End If
        End Sub
    
        Sub Search3()
            DataGridView1.ClearSelection()
            Dim list As BindingList(Of Item) = DirectCast(DataGridView1.DataSource, BindingList(Of Item))
            Dim searchText As String = SearchTextBoxDropDown.Text.ToLowerInvariant()
            Dim firstRowIndex As Integer = -1
            For i As Integer = 0 To list.Count - 1
                If list(i).LowerInvariant.Contains(searchText) Then
                    DataGridView1.Rows.Item(i).Selected = True
                    If firstRowIndex = -1 Then
                        firstRowIndex = i
                    End If
                End If
            Next
            If firstRowIndex <> -1 Then
                DataGridView1.FirstDisplayedScrollingRowIndex = firstRowIndex
            End If
        End Sub
    
        Shared Sub Watch(action As Action, count As Integer)
            Dim sw As New Stopwatch()
            sw.Start()
            For i As Integer = 1 To count
                action.Invoke()
            Next
            sw.Stop()
            Dim elapsed As String = sw.Elapsed.ToString()
            Debug.WriteLine(elapsed)
            MessageBox.Show(elapsed)
        End Sub
    
        Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
            Watch(AddressOf Search1, 10)
        End Sub
    
        Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
            Watch(AddressOf Search2, 10)
        End Sub
    
        Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
            Watch(AddressOf Search3, 10)
        End Sub
    
    End Class
    
    0 comments No comments