[Webinar] Streamline your web hosting managementRegister Today

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 753
  • Last Modified:

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;
            }
 
0
LenTompkins
Asked:
LenTompkins
  • 7
  • 7
1 Solution
 
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
The new generation of project management tools

With monday.com’s project management tool, you can see what everyone on your team is working in a single glance. Its intuitive dashboards are customizable, so you can create systems that work for you.

 
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
 
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

Featured Post

Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

  • 7
  • 7
Tackle projects and never again get stuck behind a technical roadblock.
Join Now