InvalidOperationException Occurs When Editing the Last Row After Previously Deleting the last Row from a DataGrid

I am having a problem when I delete the last row of a table.  The delete will work properly, but if I then edit the new last row I am getting an Invalid Operation Exception from my CurrentChanged Event Handler.   What I noticed is that when I am deleting the last record, it does the delete to the datagrid then jumps to the CurrentChanged event handler and after it finishes, it goes back and finishes the rest of the delete routine.  Why is it doing this?  Any thoughts?

    // Instantiate binding source for binding navigator
            this.m_srcCollectionHistoryType = new BindingSource();
            this.m_srcCollectionHistoryType.DataSource = this.m_dsCollectionHistory.CollectionHistoryType;

            this.grdCollectionHistoryType.AutoGenerateColumns = false;

            this.grdCollectionHistoryType.DataSource = this.m_srcCollectionHistoryType;
            this.navCollectionHistoryType.BindingSource = this.m_srcCollectionHistoryType;

this.m_srcCollectionHistoryType.CurrentChanged += new EventHandler(m_srcCollectionHistoryType_CurrentChanged);


//Event Handlers
        private void btnDeleteCollectionHistoryType_Click(object sender, EventArgs e)
        {
            DataRowView rowView =
                (DataRowView)this.grdCollectionHistoryType.CurrentRow.DataBoundItem;
            try
            {
                string currentRow = rowView["Type"].ToString();
                if (currentRow == "Unknown")
                {
                    MessageBox.Show("You cannot delete an 'Unknown'");
                    return;
                }

                rowView.Delete();      <-- Jumps to CurrentChanged event handler after executing this statement
                int recordsAffected =
                    this.m_adpCollectionHistoryType.Update(rowView.Row);
                MessageBox.Show(string.Format("Collection History Type: '{0}' deleted.", currentRow));
            }
            catch (InvalidConstraintException)
            {
                MessageBox.Show("You cannot delete a record that is linked to records in Collection History Key Table!");
            }
            catch (SqlException)
            {
                MessageBox.Show("You cannot delete this record!");
            }
        }

private void m_srcCollectionHistoryType_CurrentChanged(object sender, EventArgs e)
        {
            if (this.grdCollectionHistoryType.CurrentRow == null) return;
           
 
            if (this.grdCollectionHistoryType.CurrentRow.Index == (this.grdCollectionHistoryType.RowCount - 1))
            {
                this.grdCollectionHistoryType.DataSource = null;                     <---- Causes InvalidOperationException occurs here
                this.grdCollectionHistoryType.DataSource = m_srcCollectionHistoryType;
            }
 
LenTompkinsAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

13598Commented:
CurrentChanged is triggered when the bound value changes but you are trying to use the datagridview when erroring, correct? grdCollectionHistoryType is yout dgv?
It may be that you deleted the last row but didn't commit the change to the bindingsource yet?
So currentrow and bindingsource row are out of synch one doesnt exist and the other one still does?
You could try either changing your code to use the bindingsource for what you are doing or commiting the changes righ before by using bindingsource.endedit at the beginning of your event?
0
LenTompkinsAuthor Commented:
I am new to coding in C# but how do I commit the change to the binding source?  I thought that when you update the table adapter, the binding source gets updated as well.
0
13598Commented:
Using:
Bindingsource.EndEdit()     (Replace Bindingsource with the actual name of your bindingsource)
When the EndEdit method is called, all pending changes are applied to the underlying data source.
0
Cloud Class® Course: Python 3 Fundamentals

This course will teach participants about installing and configuring Python, syntax, importing, statements, types, strings, booleans, files, lists, tuples, comprehensions, functions, and classes.

LenTompkinsAuthor Commented:
I just tried that and the delete works, but when I then edit the last row of the table I am getting an "Operation is not valid because it results in a re-entrant call to the set current cell address core function.  It is occrring in:
 if (this.grdCollectionHistoryType.CurrentRow.Index == (this.grdCollectionHistoryType.RowCount - 1))
            {
                this.grdCollectionHistoryType.DataSource = null;
                this.grdCollectionHistoryType.DataSource = m_srcCollectionHistoryType;
            }
I added the following code so that when I added a new record to the end of the table and then deleted it, the code was abending.  I thought this would resolve it, but now after I have added a new record, then deleted it, and then edited the last row, I get this error.  
I would move this to the delete routine, but after I do:
rowView.Delete();    it jumps to the CurrentChanged method.

Am I going about this all wrong?
0
13598Commented:
What are you trying to accomplish with that code?
0
LenTompkinsAuthor Commented:
I added the code to bypass an error that I was getting after deleting the last row of the table.  I just commented out that code, and added a new record then deleted it.  After it does the delete statement, it jumps to the Current Changed method and abends with System Index out of range exception. Everytime I come into this current changed, should I perform an end-Edit so that the binding source is in sync?
0
13598Commented:
Are you saying it abends in the currentchanged even if there is no code there?
Remove the code and let's figure out the problem.
That code was just because of the error correct? You don't actually need to do anything?
0
LenTompkinsAuthor Commented:
Here is the routine the way I now have it:
private void m_srcCollectionHistoryType_CurrentChanged(object sender, EventArgs e)
        {
            if (this.grdCollectionHistoryType.CurrentRow == null) return;

            if (this.grdCollectionHistoryType.CurrentRow.Index == (this.grdCollectionHistoryType.RowCount - 1))
            {
          //      this.m_srcCollectionHistoryType.EndEdit();
               // this.grdCollectionHistoryType.DataSource = null;
               // this.grdCollectionHistoryType.DataSource = m_srcCollectionHistoryType;
            }

            //Save original 'Type' column in case it needs to be restored
            int rowIndex = this.grdCollectionHistoryType.CurrentRow.Index;

            DataRow row = this.m_dsCollectionHistory.CollectionHistoryType.Rows[rowIndex];

            string origType = row["Type", DataRowVersion.Original].ToString();

            //this.grdCollectionHistoryType.EndEdit();
            try
            {
                DataRowView drv = (DataRowView)this.grdCollectionHistoryType.CurrentRow.DataBoundItem;

                if (drv.Row.RowState == DataRowState.Modified)
                {
                    if (origType == "Unknown")
                    {
                        MessageBox.Show("You cannot modify an 'Unknown'");
                        // Change Type back to "Unknown"
                        this.m_dsCollectionHistory.CollectionHistoryType[rowIndex].Type = origType;
                        return;
                    }

                    //Update "Last Touched By" & "Last Touched Date" columns before saving updated record
                    this.m_dsCollectionHistory.CollectionHistoryType[rowIndex].LastTouchedBy =
                                            SystemInformation.UserName;
                    this.m_dsCollectionHistory.CollectionHistoryType[rowIndex].LastTouchedDate = DateTime.Now;

                    int recordsAffected =
                         this.m_adpCollectionHistoryType.Update(drv.Row);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
   
When I delete the last row, after the delete, it goes right to this current changed and I am getting an error on:
 DataRowView drv = (DataRowView)this.grdCollectionHistoryType.CurrentRow.DataBoundItem;

saying the row index is out of bounds.  
How should I resolve this?
0
13598Commented:
I don't fully understand what you are doing and why you are doing it in this event but to solve your issue I would try not using CurrentRow since that is the problem. Your CurrentRow is not pointing at the right place.
Doesn't your e arg give you the rowindex. Use that instead?
Something like:
DataRowView drv = (DataRowView)this.grdCollectionHistoryType.e(RowIndex).DataBoundItem;
0
LenTompkinsAuthor Commented:
The dataRow View statement doesn't work here.  It says that Systems.Form.datagrid doesn't contain a definition for e.

I have this routine, because, when I want to change a row's text we have one row that can never be changed.  I was defining a row view to see if the original text =" UnKnown".  If it is, the change will be cancelled, otherwise it continues on.  where else can I perform this test?
0
13598Commented:
Do you have a rowvalidating event?
The rowvalidating event has e.cancel = true to let you cancel it if it doesn't comply.
You can perform your tests there and determine whether to continue or cancel.
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
LenTompkinsAuthor Commented:
No I don't but I will try that now.  Thank you for all of your assistance.  I'll try it now and get back to you.
0
LenTompkinsAuthor Commented:
Yes,  Thank you very much.  I finally solved the problem by getting rid of CurrentChanged performing a Row Validation.   Then I asked if the field was equal to the string Unknown and if it was, I then created the data row view to determine if the row state was modified.  It now works.
I and some other new programmers have been working on this problem for over 1 week.
0
13598Commented:
Nicely done.  Glad I could help.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
C#

From novice to tech pro — start learning today.