Avatar of PeterBaileyUk
PeterBaileyUk
 asked on

vb.net datagrid scroll automatically to the first found row

I have a sub that does a search and selects (highlights) the rows. How can I make it scroll to that first row automatically?

    Private Shadows Sub OnKeyUp(sender As Object, e As KeyEventArgs) Handles TxtBulkShortDesc.KeyUp
        Dim tb = DirectCast(sender, TextBox)
        If tb.Equals(TxtBulkShortDesc) Then
            If e.KeyCode.Equals(Keys.Enter) Then
                DataGridViewStringsBulk.SearchAndSelect(tb.Text, CBBulkSearchDesc.SelectedItem, True)
                tb.Clear()
                e.Handled = True
            End If
        End If

    End Sub

Open in new window


extensions
Public Function ConvertToDataTable(Of T)(ByVal source As IEnumerable(Of T)) As DataTable
        Dim properties As PropertyDescriptorCollection = TypeDescriptor.GetProperties(GetType(T))
        Dim table As DataTable = New DataTable()

        For i As Integer = 0 To properties.Count - 1
            Dim [property] As PropertyDescriptor = properties(i)
            If [property].PropertyType.IsGenericType AndAlso [property].PropertyType.GetGenericTypeDefinition().Equals(GetType(Nullable)) Then
                table.Columns.Add([property].Name, [property].PropertyType.GetGenericArguments()(0))
            Else
                table.Columns.Add([property].Name, [property].PropertyType)
            End If
        Next

        Dim values(properties.Count - 1) As Object
        For Each item As T In source
            For i As Integer = 0 To properties.Count - 1
                values(i) = properties(i).GetValue(item)
            Next
            table.Rows.Add(values)
        Next

        Return table
    End Function

    <Extension()>
    Public Sub SearchAndSelect(grid As DataGridView, term As String, selector As String, Optional clearSelected As Boolean = False)
        If grid IsNot Nothing AndAlso grid.Rows.Count < 1 Then Return
        If String.IsNullOrWhiteSpace(term) Then Return
        grid.BeginEdit(True)
        Dim counter = 0
        If clearSelected Then
            For Each row In grid.SelectedRows.Cast(Of DataGridViewRow)()
                row.Selected = False
            Next
        End If

        For Each row In grid.Rows.Cast(Of DataGridViewRow)()
            If selector <> "- All Columns -" Then
                If row.Cells(selector).Value IsNot Nothing AndAlso row.Cells(selector).Value.ToString().IndexOf(term, StringComparison.OrdinalIgnoreCase) <> -1 Then
                    row.Selected = True
                    counter += 1
                    Continue For
                End If
            Else
                For Each column In grid.Columns.Cast(Of DataGridViewColumn)()
                    If row.Cells(column.Name).Value IsNot Nothing AndAlso row.Cells(column.Name).Value.ToString().IndexOf(term, StringComparison.OrdinalIgnoreCase) <> -1 Then
                        row.Selected = True
                        counter += 1
                        Exit For
                    End If
                Next
            End If
        Next
        grid.EndEdit()

        If counter = 0 Then MessageBox.Show(String.Format("No rows were found that matched - {0}", term))
    End Sub

Open in new window

Visual Basic.NET* DataGridView

Avatar of undefined
Last Comment
PeterBaileyUk

8/22/2022 - Mon
Fernando Soto

Hi Peter;

The DataGridView has a property called FirstDisplayedScrollingRowIndex which when set should bring the selected row to the top. You can set it like so
grid.FirstDisplayedScrollingRowIndex = IntegerRowIndexHere

Open in new window

PeterBaileyUk

ASKER
yes I read about that but didnt see how to get that number is it the first value of counter or IndexOf?
ASKER CERTIFIED SOLUTION
Fernando Soto

THIS SOLUTION ONLY AVAILABLE TO MEMBERS.
View this solution by signing up for a free trial.
Members can start a 7-Day free trial and enjoy unlimited access to the platform.
See Pricing Options
Start Free Trial
GET A PERSONALIZED SOLUTION
Ask your own question & get feedback from real experts
Find out why thousands trust the EE community with their toughest problems.
PeterBaileyUk

ASKER
I got a syntax error with the square brackets (The error message said collection cannot be converted) so i tried with circular it did go to a row but not the first:

If (DataGridViewStrCommon.SelectedRows.Count > 0) Then

            DataGridViewStrCommon.FirstDisplayedScrollingRowIndex = DataGridViewStrCommon.Rows.IndexOf(DataGridViewStrCommon.SelectedRows(0))
        End If

Open in new window

I started with Experts Exchange in 2004 and it's been a mainstay of my professional computing life since. It helped me launch a career as a programmer / Oracle data analyst
William Peck
Fernando Soto

Sorry about that Peter but the code I posted was C# and not VB.Net. As far as moving it to the very top row there must be enough rows under the one to be displayed in the top row position for it to move to the top.
SOLUTION
it_saige

THIS SOLUTION ONLY AVAILABLE TO MEMBERS.
View this solution by signing up for a free trial.
Members can start a 7-Day free trial and enjoy unlimited access to the platform.
See Pricing Options
Start Free Trial
⚡ FREE TRIAL OFFER
Try out a week of full access for free.
Find out why thousands trust the EE community with their toughest problems.
PeterBaileyUk

ASKER
its interesting it does work but if I scroll down from the top I have vehicle range A6 and the last I have is a ZZR A6 it scrolled to the ZZR A6 and I had hoped it would have gone to the A6 as A6 was nearest to the top.
it_saige

Whoops, I forgot that the SelectedRows collection is filled in reverse, just use Last() to get the Last Item (which is actually the first item selected) in the list and use index on it; e.g. -
<Extension()>
Public Sub SearchAndSelect(grid As DataGridView, term As String, selector As String, Optional clearSelected As Boolean = False)
    If grid IsNot Nothing AndAlso grid.Rows.Count < 1 Then Return
    If String.IsNullOrWhiteSpace(term) Then Return
    grid.BeginEdit(True)
    Dim counter = 0
    If clearSelected Then
        For Each row In grid.SelectedRows.Cast(Of DataGridViewRow)()
            row.Selected = False
        Next
    End If

    For Each row In grid.Rows.Cast(Of DataGridViewRow)()
        If selector <> "- All Columns -" Then
            If row.Cells(selector).Value IsNot Nothing AndAlso row.Cells(selector).Value.ToString().IndexOf(term, StringComparison.OrdinalIgnoreCase) <> -1 Then
                row.Selected = True
                counter += 1
                Continue For
            End If
        Else
            For Each column In grid.Columns.Cast(Of DataGridViewColumn)()
                If row.Cells(column.Name).Value IsNot Nothing AndAlso row.Cells(column.Name).Value.ToString().IndexOf(term, StringComparison.OrdinalIgnoreCase) <> -1 Then
                    row.Selected = True
                    counter += 1
                    Exit For
                End If
            Next
        End If
    Next
    grid.EndEdit()

    If counter = 0 Then MessageBox.Show(String.Format("No rows were found that matched - {0}", term))
    If grid.SelectedRows.Count > 0 Then
        grid.FirstDisplayedScrollingRowIndex = grid.SelectedRows.Cast(Of DataGridViewRow).Last().Index
    End If
End Sub

Open in new window


You could also Reverse the list and choose the first item - whichever works for you; e.g. -
<Extension()>
Public Sub SearchAndSelect(grid As DataGridView, term As String, selector As String, Optional clearSelected As Boolean = False)
    If grid IsNot Nothing AndAlso grid.Rows.Count < 1 Then Return
    If String.IsNullOrWhiteSpace(term) Then Return
    grid.BeginEdit(True)
    Dim counter = 0
    If clearSelected Then
        For Each row In grid.SelectedRows.Cast(Of DataGridViewRow)()
            row.Selected = False
        Next
    End If

    For Each row In grid.Rows.Cast(Of DataGridViewRow)()
        If selector <> "- All Columns -" Then
            If row.Cells(selector).Value IsNot Nothing AndAlso row.Cells(selector).Value.ToString().IndexOf(term, StringComparison.OrdinalIgnoreCase) <> -1 Then
                row.Selected = True
                counter += 1
                Continue For
            End If
        Else
            For Each column In grid.Columns.Cast(Of DataGridViewColumn)()
                If row.Cells(column.Name).Value IsNot Nothing AndAlso row.Cells(column.Name).Value.ToString().IndexOf(term, StringComparison.OrdinalIgnoreCase) <> -1 Then
                    row.Selected = True
                    counter += 1
                    Exit For
                End If
            Next
        End If
    Next
    grid.EndEdit()

    If counter = 0 Then MessageBox.Show(String.Format("No rows were found that matched - {0}", term))
    If grid.SelectedRows.Count > 0 Then
        grid.FirstDisplayedScrollingRowIndex = grid.SelectedRows.Cast(Of DataGridViewRow).Reverse()(0).Index
    End If
End Sub

Open in new window

-saige-
⚡ FREE TRIAL OFFER
Try out a week of full access for free.
Find out why thousands trust the EE community with their toughest problems.
PeterBaileyUk

ASKER
thank you both
PeterBaileyUk

ASKER
our messages crossed!
PeterBaileyUk

ASKER
you might wonder why I closed, it was because I thought that that was the way it was. maybe a moderator will change to the best and assisted but using the last message if that makes sense
All of life is about relationships, and EE has made a viirtual community a real community. It lifts everyone's boat
William Peck