title: Highlight DataGridViewRows based on value comparison with other rows
body: <p>I have a Part class with the fields list in the code below. I have a DataGridView control, which I am filtering with the Advanced DGV (ADGV) DLL from NUGET. I must include the ADGV in my winform. I currently have a DataGridView, a search box on the form, and a button to run the following function. I need to go through all of the visible rows, collect a unique list of part numbers with their most recent revisions, and then color the rows in DataGridView which are out of date by checking the part number and rev on each row against the mostuptodate list. For 45,000 entries displayed in DataGridView, this take ~17 secs. For ~50 entries, it take ~1.2 seconds. This is extremely inefficient, but I can't see a way to cut the time down. </p>
  
  <pre><code>Sub highlightOutdatedParts()
      'Purpose: use the results in the datagridview control, find the most recent revision of each part, and 
      '           highlight all outdated parts relative to their respective most recent revisions
      'SORT BY PART NUMBER AND THEN BY REV
      If resultsGrid.ColumnCount = 0 Or resultsGrid.RowCount = 0 Then Exit Sub
      Dim stopwatch As New Stopwatch
      stopwatch.Start()
      resultsGrid.Sort(resultsGrid.Columns("PartNumber"), ListSortDirection.Ascending)
      Dim iBag As New ConcurrentBag(Of Part)
      Dim sortedList As Generic.List(Of Part)
      For Each row As DataGridViewRow In resultsGrid.Rows
          If row.Visible = True Then
              Dim iPart As New Part()
              Try
                  iPart.Row = row.Cells(0).Value
                  iPart.Workbook = CStr(row.Cells(1).Value)
                  iPart.Worksheet = CStr(row.Cells(2).Value)
                  iPart.Product = CStr(row.Cells(3).Value)
                  iPart.PartNumber = CStr(row.Cells(4).Value)
                  iPart.ItemNo = CStr(row.Cells(5).Value)
                  iPart.Rev = CStr(row.Cells(6).Value)
                  iPart.Description = CStr(row.Cells(7).Value)
                  iPart.Units = CStr(row.Cells(8).Value)
                  iPart.Type = CStr(row.Cells(9).Value)
                  iPart.PurchCtgy = CStr(row.Cells(10).Value)
                  iPart.Qty = CDbl(row.Cells(11).Value)
                  iPart.TtlPerProd = CDbl(row.Cells(12).Value)
                  iPart.Hierarchy = CStr(row.Cells(13).Value)
                  iBag.Add(iPart)
              Catch ice As InvalidCastException
              Catch nre As NullReferenceException
              End Try
          End If
      Next
      sortedList = (From c In iBag Order By c.PartNumber, c.Rev).ToList()  ' sort and convert to list
      Dim mostUTDRevList As New Generic.List(Of Part)     ' list of most up to date parts, by Rev letter
      For sl As Integer = sortedList.Count - 1 To 0 Step -1   'start at end of list and work to beginning
          Dim query = From entry In mostUTDRevList    ' check if part number already exists in most up to date list
                      Where entry.PartNumber = sortedList(sl).PartNumber
                      Select entry
          If query.Count = 0 Then     ' if this part does not already exist in the list, add.
              mostUTDRevList.Add(sortedList(sl))
          End If
      Next
      'HIGHLIGHT DATAGRIDVIEW ROWS WHERE PART NUMBERS ARE OUT OF DATE
      For Each row As DataGridViewRow In resultsGrid.Rows
          ' if that part with that Rev does not exist in the list, it must be out of date
          Try
              Dim rowPN As String = CStr(row.Cells(4).Value).ToUpper  ' get part number
              Dim rowR As String = CStr(row.Cells(6).Value).ToUpper   ' get Rev
              Dim query = From entry In mostUTDRevList    ' check if that part number with that Rev is in the list.
                          Where entry.PartNumber.ToUpper.Equals(rowPN) AndAlso
                          entry.Rev.ToUpper.Equals(rowR)
                          Select entry
              If query.Count = 0 Then     ' if the part is out of date highlight its' row
                  row.DefaultCellStyle.BackColor = Color.Chocolate
              End If
          Catch ex As NullReferenceException
          Catch ice As InvalidCastException
          End Try
      Next
      resultsGrid.Select()
      stopwatch.Stop()
      If Not BackgroundWorker1.IsBusy() Then timertextbox.Text = stopwatch.Elapsed.TotalSeconds.ToString &amp; " secs"
      MessageBox.Show("Highlighting completed successfully.")
  End Sub
  </code></pre>