TonyW TonyW - 3 months ago 20
Vb.net Question

DataGrid SelectedItems for each loop exeption

As i'm scrolling through the datagrid and selecting items on and off the visible screen, it throws the following exception.

Object reference not set to an instance of an object.


Dim sn as string is the culprit...

For Each item In asset_MasterDataGrid.SelectedItems
If item IsNot Nothing Then
Dim snIndex As Integer = asset_MasterDataGrid.Columns.IndexOf(asset_MasterDataGrid.Columns.LastOrDefault(Function(c) c.Header = "serial num"))
Dim sn As String = DirectCast(asset_MasterDataGrid.SelectedCells(snIndex).Column.GetCellContent(item), TextBlock).Text
variables.selectedAssets.Add(sn)
End If
Next


When
EnableRowVirtualization="True"
is true, I get the error. I'm assuming this is because once I scroll off the screen, while having rows selected, those rows no longer exist.

How do I avoid this, without turning off virtualization?

Answer
' No need to do this every time; the column won't move.
Dim snIndex As Integer = asset_MasterDataGrid.Columns.IndexOf(asset_MasterDataGrid.Columns.LastOrDefault(Function(c) c.Header = "serial num"))

For Each item In asset_MasterDataGrid.SelectedItems
    If item IsNot Nothing Then

       ' In the language of my people, we would say
       '    var drv = item as System.Data.DataRowView;
       Dim drv = DirectCast(item, System.Data.DataRowView)

       Dim sn As String = drv.Row[snIndex].ToString()
       variables.selectedAssets.Add(sn)
    End If
Next

I think you were getting the null reference exception because you were trying to cast some part of selected item to a TextBlock, but there's nothing in there that's castable to that.

In WPF, SelectedItems means the data items that are being displayed in the UI, not the actual UI stuff. It's a subset of the whole collection items that you gave to ItemsSource -- whatever those are, that's what it's "selecting" when the user clicks on the grid. I had to populate my DataGrid like so:

myDataGrid.ItemsSource = myDataTable.DefaultView;

DefaultView returns a DataView which implements IEnumerable. Enumerate it, and it gives you DataRowView instances. And those are what the DataGrid gives you back in SelectedItems.

But I know just about zero about DataTable. If you did it some other way, if there is some other way, you may get something else back. So put a breakpoint in that loop and examine item; see what type it is. It's going to be something that represents one of your data rows, or I'll eat my hat(1).

(1) That's an exclusive OR.

Comments