views:

49

answers:

2

Howdy, all!

I'm still relatively new to LINQ, and have done more stumbling around than anything, but I have really liked what I have seen so far. So with that in mind, I have a VB.NET search routine, part of which is provided, below, that checks all Text cells in a DataGridView for a given string (inclusive), using a basic set of nested loops to perform the search:

' Search for the first occurrence of the given string
For Each row As DataGridViewRow In dgvMembers.Rows
    ' Skip the new row
    If row.IsNewRow Then Exit For

    ' Loop through all the cells in the current row
    For Each cell As DataGridViewCell In row.Cells
        ' Skip non-text cells
        If cell.GetType IsNot GetType(DataGridViewTextBoxCell) Then Continue For

        ' Search for our matching text
        If cell.Value.ToString.ToUpper.Contains(searchText) Then
            ' Select the cell if we have a match
            dgvMembers.CurrentCell = cell
            WriteMessage("String '{0}' found.", searchText)
            Exit Sub
        End If
    Next
Next

' If we get to this point, we didn't find anything
WriteMessage("String '{0}' NOT found.", searchText)

Pretty straightforward. Now, my question is: is there a way to replicate this behavior using LINQ? Basically I would like the query to select (or return) the first DataGridViewCell whose text contains the search string. I've done some tinkering with sub-queries and the like, but I'm still having trouble wrapping my brain around the concepts (too many years of writing T-SQL, I guess).

Obviously the nested loop works fine, so this is more of a curiosity, really. Thanks in advance!

+1  A: 

I was able to use this code with some success:

Dim qry = From theRow as DataGridViewRow In dgvMembers.Rows, _
               theCell as DataGridViewCell In theRow.Cells _
          Where theCell.Value.ToString.ToUpper = searchText _
          Select theCell


Dim matchCell as DataGridViewCell = qry.First

dgvMembers.CurrentCell = matchCell

... etc...

knslyr
Wow, that's so...elegant. :-) Did not even *think* of querying from 2 things at once. I have not had a chance to implement it yet, but it looks awesome. +1 for simplicity! I'll try it out and let you know how it works. Thanks!
Mike Loux
That worked really well. Just had to add a Try...Catch block to handle when the row is a new row (can't filter for it in the Where clause because we're referring to it as if it has data in the From clause already), but other than that, it was perfect. Thanks again!!!!
Mike Loux
My pleasure, glad it worked for you :)
knslyr
knslyr - Robert Jordan fan? :-)
Mike Loux
Indeed I am, heh ;)
knslyr
A: 

Posting a full code snippet using knslyr's response, but in the context of my original code, just for posterity:

Try
    ' Search (case insensitive) for the first occurrence of the given string
    Dim foundCell As DataGridViewCell = (
        From row As DataGridViewRow In dgvMembers.Rows,
        cell As DataGridViewCell In row.Cells
        Where cell.Value.ToString.ToUpper.Contains(searchText)
        Select cell
    ).First

    ' If we have a match, select it
    If foundCell IsNot Nothing Then
        ' Select the cell if we have a match
        dgvMembers.CurrentCell = foundCell
        WriteMessage("String '{0}' found.", searchText)
    Else
        ' No cell found.  Whoops.
        WriteMessage("String '{0}' NOT found.", searchText)
    End If
Catch ex As Exception
    ' An exception probably means the New row was reached.  So, no dice.
    WriteMessage("String '{0}' NOT found.", searchText)
End Try
Mike Loux
This works, but having to trap an exception kind of bugs me. Anybody know of a way to get around that? Seems like it's not doable, because the exception is thrown by searching on the new row, which has no cells, and we're specifying the cell search right off the bat. I tried doing "From row in dgv.rows where not row.isnewrow" but that wouldn't compile. There's gotta be a way around that...maybe. :-)
Mike Loux