views:

422

answers:

1

I have a DataGridView that is bound to a list of objects called "BaseChange". The BaseChange objects are made up of 4 properties...

  • ChangeType
  • ChangeStatus
  • ChangeDescription
  • LastChangeDate

The datagridview has columns for all 4 values as well as a 5th (a checkbox column called "colIsSelected"). There is no problem binding the list to the grid and displaying the items.

The problem is that the query that gets the selected items in the grid is giving me an implicit cast error when option strict is enabled.

This is the query...

Dim _changes As List(Of BaseChange)

_changes = (From _row As DataGridViewRow In dgvChanges.Rows() _
            Where Convert.ToBoolean(_row.Cells(NAME_COLUMN_IS_SELECTED).Value) = True _
            Select DirectCast(_row.DataBoundItem, BaseChange)).ToList()

...and it produces the correct results with option strict off. The implicit cast squiggle is on the "row As DataGridViewRow" code, and the full message is "Implicit conversion from 'Object' to 'System.Windows.Forms.DataGridViewRow'*".

If I exclude the "As DataGridViewRow" from the query, I get a late binding error on the _row.Cells and _row.DataBoundItem and this also fails option strict.

I need this to work with Option Strict enabled, and in VB. Am I missing something here? Anyone have suggestions?

+2  A: 
(From _row As DataGridViewRow In dgvChanges.Rows()

your type of the _row object has to match the single version of the collection type.

as in:

    'Assumes Option Strict On and Option Implicit On
    Dim _changes = (From _row In dgvChanges.Rows() _            
           Where Convert.ToBoolean(ctype(_row,DataGridViewRow).Cells(NAME_COLUMN_IS_SELECTED).Value) = True _           
Select DirectCast(ctype(_row,DataGridViewRow).DataBoundItem, BaseChange)).ToList()

Linq sees your Rows() collection as IEnumerable, so your row is an object. Explanation at the bottom goes into more detail.

Added:

Adding Option Infer should simplify this.

See for more details:

http://stackoverflow.com/questions/194278/what-is-the-best-way-to-mix-vb-nets-option-strict-and-the-new-option-infer-direc

and

http://social.msdn.microsoft.com/forums/en-US/linqprojectgeneral/thread/e3ec737a-42f8-4767-a190-78390202a991/

Explanation: I did some more digging as to why it isn't simpler. RowCollection for a DataGridView implements the older IEnumberable interface which returns objects, while newer collection types Implement the Generic IEnumerable(Of T) Interface, which returns the type directly, removing the need for casting.

See msdn for implemented interfaces.

Tim Hoolihan
This fixes the problem, but I am still a bit confused by why the Rows() collection is not actually seen as a collection of DataGridViewRow. Do you know where I can get more info on this? This is for a small application but I am concerned about the amount of casting that could be needed in a larger application. I've not had to do this for other (generic) collection types, is this something to expect when using LINQ against non-generic collections? Is it as big of a performance hit as it appears to be?
StingyJack
i added some text at the bottom, basically, add Option Infer
Tim Hoolihan
I added the "Explanation" paragraph at the bottom which explains why the cast is required, when it is not in most code samples you see.
Tim Hoolihan
Thanks, that makes great sense.
StingyJack