Sorting DataGridView causes problems

chris1028

Newcomer
Joined
Sep 23, 2009
Messages
8
Hello Xtreme - my first post: please be kind.

My application has a read-only datagridview dgvFound fed from a datatable dtFound. This datagridview is permanently displayed whilst the application is running.

dtFound is declared public in a module (and exists whilst the application is running).

dtFound is fed from any one of around thirty different "finders" that are grouped in three user controls - these finders run sprocs on MSSQL2005 and clear/refill dtFound.

Everything works perfectly with dgvFound refreshing nicely in the main form when one of the finders raises a dtFoundIsReady event...
... until the user clicks the header of dgvFound to sort. After the sort everything goes pear-shaped with a NullReferenceException.

Some code:
Code:
        ...yada yada yada to prepare cmd

        '// exec the sproc
        conn1.Open()
        Dim oDr As SqlDataReader = cmd.ExecuteReader()

        '// clear any entries in existing datatable dtFound
        dtFound.Rows.Clear()
        dtFound.Columns.Clear()
        dtFound.Clear()

        '// refill dtFound
        Dim i As Integer
        Dim count As Integer = oDr.FieldCount - 1

        '//add columns
        For i = 0 To count
            dtFound.Columns.Add(oDr.GetName(i), oDr.GetFieldType(i))
        Next

        '//add rows
        Do While oDr.Read()
            Dim r As DataRow = dtFound.NewRow
            For i = 0 To count
                r(i) = oDr.Item(i)
            Next [B][COLOR="Red"]
'NullReferenceException on next line if dgvFound has been sorted by user [/COLOR]
            dtFound.Rows.Add(r) [/B]
        Loop

        '// raise an event to let the application know dtFound is filled
and then in the event handler:
Code:
        Me.dgvFound.DataSource = dtFound

        '// WORKAROUND to evade NullReferenceException after sort
        Dim i As Integer
        For i = 0 To dgvFound.ColumnCount - 1
            Me.dgvFound.Columns(i).SortMode = DataGridViewColumnSortMode.NotSortable
        Next

The users can live without sorting - so for the time being I have simply turned sort off, but I would like to understand what is happening here, and how I might be able to leave sorting on.

Chris
 
Test: find 2 columns x 30 rows, sort the datagrid, rerun the same 2 x 30 to throw the exception.
dtFound is alive when the exception is thrown:

>? oDr.fieldcount
2
>? count
1
>? i
2
>? dtfound.rows.count
2
>? dtfound.columns.count
2

Here is a (partial) stack trace:
Code:
System.NullReferenceException was unhandled
  Message="La référence d'objet n'est pas définie à une instance d'un objet."
  Source="System.Data"
  StackTrace:
    à System.Data.Index.CompareRecords(Int32 record1, Int32 record2)
    à System.Data.Index.IndexTree.CompareNode(Int32 record1, Int32 record2)
    à System.Data.RBTree`1.RBInsert(Int32 root_id, Int32 x_id, Int32 mainTreeNodeID, Int32 position, Boolean append)
    à System.Data.RBTree`1.InsertAt(Int32 position, K item, Boolean append)
    à System.Data.Index.InsertRecord(Int32 record, Boolean fireEvent)
    à System.Data.Index.ApplyChangeAction(Int32 record, Int32 action, Int32 changeRecord)
    à System.Data.DataTable.RecordStateChanged(Int32 record1, DataViewRowState oldState1, DataViewRowState newState1, Int32 record2, DataViewRowState oldState2, DataViewRowState newState2)
    à System.Data.DataTable.SetNewRecordWorker(DataRow row, Int32 proposedRecord, DataRowAction action, Boolean isInMerge, Int32 position, Boolean fireEvent, Exception& deferredException)
    à System.Data.DataTable.InsertRow(DataRow row, Int32 proposedID, Int32 pos, Boolean fireEvent)
    à System.Data.DataRowCollection.Add(DataRow row)
    à <myapplication>.ucFinderXxxx.butShowSearch_Click(Object sender, EventArgs e) dans D:\Development\Projects\<myapplication>\ucFinderXxxx.vb:ligne 158
Sorry it is in "Microsoft French".

Chris
 
mmm - didn't know I could do this:
Code:
>? r
{System.Data.DataRow}
    HasErrors: False
    Item: In order to evaluate an indexed property, the property must be qualified and the arguments must be explicitly supplied by the user.
    Item: In order to evaluate an indexed property, the property must be qualified and the arguments must be explicitly supplied by the user.
    Item: In order to evaluate an indexed property, the property must be qualified and the arguments must be explicitly supplied by the user.
    Item: In order to evaluate an indexed property, the property must be qualified and the arguments must be explicitly supplied by the user.
    Item: In order to evaluate an indexed property, the property must be qualified and the arguments must be explicitly supplied by the user.
    ItemArray: {Length=2}
    RowError: ""
    RowState: Added {4}
    Table: {System.Data.DataTable}
>? oDr
{System.Data.SqlClient.SqlDataReader}
    Depth: 0
    FieldCount: 2
    HasRows: True
    IsClosed: False
    Item: In order to evaluate an indexed property, the property must be qualified and the arguments must be explicitly supplied by the user.
    RecordsAffected: -1
    VisibleFieldCount: 2

Chris
 
and one more:
Code:
>? dtFound
{System.Data.DataTable}
    CaseSensitive: False
    ChildRelations: {System.Data.DataRelationCollection.DataTableRelationCollection}
    Columns: {System.Data.DataColumnCollection}
    Constraints: {System.Data.ConstraintCollection}
    Container: Nothing
    DataSet: Nothing
    DefaultView: {System.Data.DataView}
    DesignMode: False
    DisplayExpression: ""
    ExtendedProperties: Count = 0
    HasErrors: False
    IsInitialized: True
    Locale: {System.Globalization.CultureInfo}
    MinimumCapacity: 50
    Namespace: ""
    ParentRelations: {System.Data.DataRelationCollection.DataTableRelationCollection}
    Prefix: ""
    PrimaryKey: {Length=0}
    RemotingFormat: Xml {0}
    Rows: {System.Data.DataRowCollection}
    Site: Nothing
    TableName: ""

Chris
 
Thanks, but no - it's not a threading issue.
It really was related to sorting - and the simple fix was to remove the sort before refilling the datatable:



Code:
...yada yada

        '// exec the sproc
        conn1.Open()
        Dim oDr As SqlDataReader = cmd.ExecuteReader()

[COLOR="RoyalBlue"]
        '// remove any dtFound sorting before refilling it
        dtFound.DefaultView.Sort = String.Empty
[/COLOR]

        '// clear any entries in existing datatable dtFound
        dtFound.Rows.Clear()
        dtFound.Columns.Clear()
        dtFound.Clear()

        '// refill dtFound
        Dim i As Integer


yada yada...

Chris
 
Back
Top