Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations TouchToneTommy on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Tough Question about NullReferenceException from Datagrid Delete 1

Status
Not open for further replies.

jonbatts

Programmer
Apr 12, 2005
114
US
I'm using a form with a datagrid to edit tables directly from the database, which I'm calling from my main form. I show this form by using MyForm.ShowDialog(). I use the following code to update the database every time the row is changed in my datagrid.
Code:
Private Sub datagrid1_currentcellchanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles DataGrid1.CurrentCellChanged


        Dim tempdataset As DataSet
        Dim tempcell As DataGridCell

        If Not DataGrid1.CurrentRowIndex = previousCell.RowNumber Then
            'create a new dataset to hold the changes that have been made to the main dataset.
            Dim datasetchanges As DataSet = New DataSet

            'me.bindingcontext(dataset1, databasename).cancelcurrentedit()

            'get the changes that have been made to the main dataset
            datasetchanges = DataSet1.GetChanges
            'check to see if any changes have been made
            If (Not (datasetchanges) Is Nothing) Then

                'there are changes that need to be made, so attempt to update the datasource by
                '   calling the update method and passing the dataset
                Try
                    'open the connection.
                    SqlConnection1.Open()
                    tempdataset = DataSet1
                    'attempt to update the data source.
                    dataAdapter.Update(datasetchanges)
                Catch updateexception As System.Exception
                    MsgBox("problem saving one or more entries.  it is most" & vbNewLine & _
                        "likely that some of your data violates foreign" & vbNewLine & _
                        "key constraints.  if problem persists please" & vbNewLine & _
                        "contact your friendly it specialist.", MsgBoxStyle.Exclamation, "error saving data")
                    DataGrid1.CurrentCell = previousCell
                    For counter As Integer = 0 To previousRow.ItemArray.GetLength(0) - 1
                        Try
                            DataSet1.Tables(databaseName).Rows(DataGrid1.CurrentRowIndex).Item(counter) = previousRow.Item(counter)
                        Catch ex As ReadOnlyException
                            'MsgBox("readonlyexception thrown")
                        End Try
                    Next
                    dataAdapter.Fill(DataSet1)
                End Try
                DataSet1.AcceptChanges()
                Try
                    SqlConnection1.Close()
                Catch connexception As Exception
                    MsgBox("problem closing sql connection." & vbNewLine & vbNewLine & "details: " & _
                        connexception.Message)
                End Try
            End If
            previousCell = DataGrid1.CurrentCell
            Try
                previousRow = DataSet1.Tables(databaseName).Rows(DataGrid1.CurrentRowIndex)
            Catch iOOREx As IndexOutOfRangeException
                MsgBox("IndexOutOfRangeException Thrown")
            End Try

        End If
    End Sub
Almost everything runs fine. When I try to delete the last row in the datagrid, I get
Code:
A first chance exception of type 'System.NullReferenceException' occurred in system.data.dll

Additional information: Object reference not set to an instance of an object.
This error doesn't occur in the form with the datagrid, it occurs in my main form which called this form. When I step through the code, the above code completes fine, and then the app goes directly to my main form and gives me this error. Been rackin' my brain all day on this one. Any ideas? Thanks.
 
The error goes to the parent form because it is unhandled.

When ever an error occurs it will move up the stack until it is either handled, or reaches the end of the stack(at which point the user gets a nast unhandled exception or JIT debugger error and the app crashes).

In this case:
1 Application thread
2 Primary Form
3 Table maintainance form
4 Delete button click event
5 Data Changed event
6 currentcellchanged event
7(Data changing, paints, refreshes etc)

(5 and 6 may be the other way, and 7 is all of the base functionality that is related to the change you made)

If an exception is thrown in level 6 and it is not handled, it will be thrown to level 5, and so on, up the stack to level 1.

As for your sepcific issue, if the datagrid is empty at this point:
Code:
previousCell = DataGrid1.CurrentCell
say like when the last cell is removed when you delete the last row, then the next time the method is called (immediatly since the cell was just removed) the first line:
Code:
If Not DataGrid1.CurrentRowIndex = previousCell.RowNumber Then
will pop.

Check to make sure that preciousCell is not nothing first, like so:

Code:
If Not previousCell.RowNumber Is Nothing AndAlso _
   Not DataGrid1.CurrentRowIndex = previousCell.RowNumber Then

AndAlso is a shortcut operator. If Condition1 of the If statment is false, Condition2 will not be checked. Similar to the OrElse operator. With OrElse, if Condition1 is true, Condition2 is not checked.

-Rick

VB.Net Forum forum796 forum855 ASP.NET Forum
[monkey]I believe in killer coding ninja monkeys.[monkey]
 
Thanks so much. Plugged in your code and it works perfectly. I still don't understand why this error wasn't being caught until the subroutine ended? Typically without a Try, an error halts the program. Does a NullReferenceException happen to not be severe enough to catch it immediately? It seems to me a thrown exception that's not immediately caught should kill the program. Any reasons other than Bill Gates thought it was a good idea? Thanks.
 
D'OH! I spoke too soon. previousCell.RowNumber isn't Nothing, and when I thought I had the problem fixed, it actually wasn't calling any of the body of my subroutine because previousCell.RowNumber initializes to 0 which is equal to Nothing. I stepped through the code while deleting a row, and even though the row had been deleted, my global variable previousCell, was still set to that cell. The cell doesn't even have to exist, I could set previousCell to cell (10, 10) in a two by two datagrid and it won't matter, unless of course I try something like datagrid1.CurrentCell = previousCell. Any more ideas?
 
Like I said, previousCell isn't the problem. I make sure that it has a value and I still get the original error. The debugger message box is titled "Microsoft Development Environment" and says
Code:
A first chance exception of type 'System.NullReferenceException' occurred in system.data.dll

Additional information: Object reference not set to an instance of an object.
The code highlighted in the debugger (the place the error is occuring) is "EditTable.ShowDialog()" where EditTable is the form with the datagrid.
 
The code highlighted in the debugger (the place the error is occuring) is "EditTable.ShowDialog()" where EditTable is the form with the datagrid.

And this occurs when you delete the last row, correct?

When you delete the last row, the CurrentCellChanged event fires, but at that point, there is no current row. Add into the initial if a check to make sure there is a valid row.

-Rick

VB.Net Forum forum796 forum855 ASP.NET Forum
[monkey]I believe in killer coding ninja monkeys.[monkey]
 
The first executable line of the code for datagrid1_currentcellchanged now reads
Code:
If (Not previousCell.RowNumber = Nothing Or previousCell.RowNumber = 0) AndAlso _
    Not DataGrid1.CurrentRowIndex = previousCell.RowNumber Then
Is that what you mean? If so, this is still giving me the same error message. Yes CurrentCellChanged is called, but it's called because CurrentCell changes from the deleted row to the row above it.
 
I'm guessing that previousCell.RowNumber is not null, but is not a valid row number (ie: 0 the header row, or -1). Which causes the error to be tossed further down in your code.

Try checking to make sure the .RowNumber >= 1

-Rick

VB.Net Forum forum796 forum855 ASP.NET Forum
[monkey]I believe in killer coding ninja monkeys.[monkey]
 
But it's not illegal for RowNumber to be 0 since it's base 0. I know it's never below 0. Is there any reason that's the only place you think the error could be occuring?
 
Row 0 is valid, except that it's a fixed row (unless you have no header). But there is also the issue that the dataset will be empty at that point, so trying to work with the data while there is none will likely throw an exception.

I don't beleive that the if line is causing the error, it's something in the code inside, or something that is called by that code. The easiest way I can see to correct it though is to not run the code in the situation where the error is thrown. Which is when you delete the last row.

Remember, the event will happen twice. Once when the cursor exits the cell, and again when it focuses on the next available cell after the delete.

-Rick

VB.Net Forum forum796 forum855 ASP.NET Forum
[monkey]I believe in killer coding ninja monkeys.[monkey]
 
I think you're right that the easiest way to correct the problem is to not run the code when I delete a row. Here's the first executable lines of code in DataGrid1_CurrentCellChanged
Code:
...
If Not DataGrid1.CurrentRowIndex = previousCell.RowNumber Then
    If DataGrid1.CurrentRowIndex = DataSet1.Tables(databaseName).Rows.Count - 2 Then
        Try
            DataGrid1.Item(DataGrid1.CurrentRowIndex + 1, 0).Equals(0)
        Catch doe As Exception
            Cursor() = Cursors.Default
            Exit Sub
        End Try
    End If
...
So far this does the trick, though I wouldn't rule out another post starting with "D'OH!". Thanks so much for your time and help Rick. If I ever see you in McDonalds, I'll buy you a Coke.
 
D'OH! So, everything worked just fine with deleting the last row, but, my code did not help when I highlighted two rows (one of them being the last row) and tried to delete them, unless the last row was the current cell. So, I was back to my original problem, trying to figure out where the exception is called. Let me tell you what I did to find out where the error was being thrown. I created a class, CustomDataGrid, which inherited DataGrid. I "wrote" (obviously had some help from VS, dropdowns, Intellisense, macros ...) an override for every function and subroutine a datagrid has. Inside each function/subroutine I wrote a try block calling the actual function. Here's an example using ProcessDialogKey
Code:
Protected Overrides Function ProcessDialogKey(ByVal keyData As System.Windows.Forms.Keys) As Boolean
    Try
        Return MyBase.ProcessDialogKey(keyData)
    Catch ex As NullReferenceException
        MsgBox("ProcessDialogKey Caught")
    End Try
End Function
I ran my program and it turns out the exception was being thrown in ProcessDialogKey. I looked at the returned error, "ex" and of course it just says "Object reference not set to an instance of an object, but I'm not sure why. Obviously I can't know without seeing the code to ProcessDialogKey.

So, after my messagebox is displayed, the form continues, and it doesn't appear to have any ill effects. Assuming I don't find any ill effects after testing some more, I'm just going to leave my try in there with an empty catch. I still wish I knew what was going on.

Hope somebody finds this interesting and I'm not just typing this for my health. Just in case there isn't anybody reading this, I used to steal purses from old ladies.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top