locked
programmatically deleting last row adds blank row RRS feed

  • Question

  • When programmatically deleting the last row in a datagridview a blank row is added.  I have already disabled the "AllowUserToAddRows" flag and that works most of the time, disabling the last blank row, except after deleting the last row. 

    Is this a known bug?  Has anyone else run into this?

    Thanks for any help!

    Michael
    Tuesday, August 11, 2009 1:45 AM

Answers

  • Hello Michael,

    Thanks for your effort to provide the sample project.

    By debug your project, I notice that the Delete Key message is passed to the ComboBox control after we call DeleteRow method. The Delete Key message will be precessed by ComboBox control, and since the AllowUserToDeleteRows is set to false, this might the reason why the deleting process is not finished. Therefore, you can try one of the following to workaround the issue.

    1. Set AllowUserToDeleteRows to true.
    2. Do not let the ComboBox process the Delete Key message by running the message after we call the DeleteRow method.

            protected override bool ProcessDataGridViewKey(KeyEventArgs e)
            {
                switch (e.KeyCode)
                {
                    case Keys.Delete:
                        if (this.ReadOnly)
                        {
                            return true;
                        }
                        else
                        {
                            DeleteRow();
                            return true;
                        }
                        break;
                }
               return base.ProcessDataGridViewKey(e);
            }

    Thanks,
    Rong-Chun Zhang
    MSDN Subscriber Support in Forum
    If you have any feedback on our support, please contact msdnmg@microsoft.com
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Welcome to the All-In-One Code Framework! If you have any feedback, please tell us.
    • Proposed as answer by NareshG Monday, August 17, 2009 12:03 PM
    • Marked as answer by Michael Warren Monday, August 17, 2009 12:07 PM
    Thursday, August 13, 2009 6:25 AM

All replies

  • What Datasource are you using ,   How do you delete last Row ? 
    Can you post your code ? 
    Tuesday, August 11, 2009 5:45 AM
  • Hello Michael,

    I also cannot reproduce the issue if the DataGridView is bound to a DataTable, I've tested it with the following code.

            DataTable dt = new DataTable();

            private void Form3_Load(object sender, EventArgs e)
            {
                dt.Columns.Add("id");
                dt.Columns.Add("name");
                for (int i = 1; i < 10; i++)
                {
                    dt.Rows.Add("Id" + i, "Name" + i);
                }
                dt.AcceptChanges();
                this.dataGridView1.AllowUserToAddRows = false;
                this.dataGridView1.DataSource = dt;
            }

            private void btnDelete_Click(object sender, EventArgs e)
            {
                this.dataGridView1.Rows.RemoveAt(this.dataGridView1.Rows.Count - 1);
            }

    Please try the above code and let me know if it helps. If not, could you please provide the source code and the detailed steps to reproduce the problem? So that we can investigate the issue locally. It is not necessary that you send out the whole of your project. We just need a simplest sample to reproduce the problem. You can remove any confidential information or business details from it. I appreciate your work on providing these information.

    Thanks,
    Rong-Chun Zhang
    MSDN Subscriber Support in Forum
    If you have any feedback on our support, please contact msdnmg@microsoft.com
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Welcome to the All-In-One Code Framework! If you have any feedback, please tell us.
    Tuesday, August 11, 2009 8:47 AM
  • This only happens on the "last row" when there is only 1 row. Here is the datagridview...

        class SBRDataGridView : DataGridView
        {
    
            protected override bool ProcessDataGridViewKey(KeyEventArgs e)
            {
                switch (e.KeyCode)
                {
                    case Keys.Delete:
                        if (this.ReadOnly)
                        {
                            return true;
                        }
                        else
                        {
                            DeleteRow();
                        }
                        break;
                }
    
                base.ProcessDataGridViewKey(e);
    
    
                return false;
            }
    
            protected void DeleteRow()
            {
                if (this.CurrentRow != null)
                {
                    if (this.CurrentRow.Index > -1)
                    {   
                        this.Rows.RemoveAt(this.CurrentRow.Index);
                    }
                }
    
            }
        }


    On our form, we have an insert button which just calls Add().


    The best way I can get this to recreate is if I have a single combo-box column, and I select an item, select another item and then (while the item is still in focus) hit the delete key.  Expected behavior is that it will delete the row leaving you with no rows.

    Steps:

    1.  Insert 1 row into the datagridview.
    2.  Click an item in the combobox.
    3.  Switch items again.
    4.  Press the delete key.



    Thanks for your help.

    Michael
    Tuesday, August 11, 2009 12:16 PM
  • Hello Michael,

    I still cannot reproduce the issue with the customized DataGridView using the following code.

            private void Form3_Load(object sender, EventArgs e)
            {
                //sbrDataGridView1 is a instance of SBRDataGridView
                this.sbrDataGridView1.AllowUserToAddRows = false;
                DataGridViewComboBoxColumn cboColumn = new DataGridViewComboBoxColumn();
                cboColumn.Items.AddRange(new object[] {
                "abc",
                "bcd",
                "cde"});
                this.sbrDataGridView1.Columns.Add(cboColumn);

            }

            private void btnAdd_Click(object sender, EventArgs e)
            {
                this.sbrDataGridView1.Rows.Add();
            }

    Could you please show us a reproducible sample project to reproduce the issue, so that we can investigate the issue locally? We can upload the project on some file sharing website and paste the url here.

    By the way, I suggest you modify the code of ProcessDataGridViewKey method like the following

            protected override bool ProcessDataGridViewKey(KeyEventArgs e)
            {
                switch (e.KeyCode)
                {
                    case Keys.Delete:
                        if (this.ReadOnly)
                        {
                            return true;
                        }
                        else
                        {
                            DeleteRow();
                        }
                        break;
                }
                return base.ProcessDataGridViewKey(e);
            }

    Thanks,
    Rong-Chun Zhang
    MSDN Subscriber Support in Forum
    If you have any feedback on our support, please contact msdnmg@microsoft.com
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Welcome to the All-In-One Code Framework! If you have any feedback, please tell us.
    Wednesday, August 12, 2009 6:49 AM

  • Project Link

    Above is a link to a simple project which demonstrates the problem.

    If you simply run the exe and press the delete key, the datagrid will act as I expect. The row will be deleted.

    If you change the item in the combobox, and then press the delete key, the grid will add a new row after the delete.

    What am I doing wrong?

    Thanks for your help!

    Michael
    Wednesday, August 12, 2009 12:40 PM
  • Hey i think Set the DataGridview's Property AllowUserToAddRows=False

    I think this might solve the problem
    Thanks Avinash Desai
    Wednesday, August 12, 2009 1:18 PM
  • It is already set like that. 

    Wednesday, August 12, 2009 1:21 PM
  • Hello Michael,

    Thanks for your effort to provide the sample project.

    By debug your project, I notice that the Delete Key message is passed to the ComboBox control after we call DeleteRow method. The Delete Key message will be precessed by ComboBox control, and since the AllowUserToDeleteRows is set to false, this might the reason why the deleting process is not finished. Therefore, you can try one of the following to workaround the issue.

    1. Set AllowUserToDeleteRows to true.
    2. Do not let the ComboBox process the Delete Key message by running the message after we call the DeleteRow method.

            protected override bool ProcessDataGridViewKey(KeyEventArgs e)
            {
                switch (e.KeyCode)
                {
                    case Keys.Delete:
                        if (this.ReadOnly)
                        {
                            return true;
                        }
                        else
                        {
                            DeleteRow();
                            return true;
                        }
                        break;
                }
               return base.ProcessDataGridViewKey(e);
            }

    Thanks,
    Rong-Chun Zhang
    MSDN Subscriber Support in Forum
    If you have any feedback on our support, please contact msdnmg@microsoft.com
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Welcome to the All-In-One Code Framework! If you have any feedback, please tell us.
    • Proposed as answer by NareshG Monday, August 17, 2009 12:03 PM
    • Marked as answer by Michael Warren Monday, August 17, 2009 12:07 PM
    Thursday, August 13, 2009 6:25 AM
  • I will give that a shot. 

    So you're saying the reason why it is adding a blank row is because the combo box is processing the delete key message as well as the datagridview?
    Thursday, August 13, 2009 9:00 AM
  • Hello Micheal,

    Yes, after DataGridView.ProcessDataGridViewKey, the message is dispatched to the ComboBox control.

    Thanks,
    Rong-Chun Zhang
    MSDN Subscriber Support in Forum
    If you have any feedback on our support, please contact msdnmg@microsoft.com

    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Welcome to the All-In-One Code Framework! If you have any feedback, please tell us.
    Thursday, August 13, 2009 10:29 AM
  • Your workaround seems to do the trick, however...

    Setting AllowUserToDeleteRows to true doesn't seem to be necessary. 

    I believe the problem is not with the delete not finishing, but with the datagrid adding a blank row AFTER the delete finishes.


    If you subscribe to the RowsRemoved event and the RowsAdded event you will notice that the row is removed THEN a new row is added.  Why would the combo box delete action be causing a row to be added?

    Thank you very much for your help.

    Attached is another project...

    Project Files
    Thursday, August 13, 2009 11:28 AM
  • Hello Michael,

    Thanks for your effort.

    You are right, after we call the DataGridView.Rows.RemoveAt(), the RowsRemoved event gets fired. However, as the message is still processed by the ComboBox control, a new row is added. Here is the callstack after the message is processed by DataGridView.

    >    DataGridViewTest.exe!DataGridViewTest.Form1.dataGridView1_RowsAdded(object sender = {SBRMaintenanceSpace.SBRDataGridView}, System.Windows.Forms.DataGridViewRowsAddedEventArgs e = {System.Windows.Forms.DataGridViewRowsAddedEventArgs}) Line 32    C#
         System.Windows.Forms.dll!System.Windows.Forms.DataGridView.OnRowsAdded(System.Windows.Forms.DataGridViewRowsAddedEventArgs e) Line 18639    C#
         System.Windows.Forms.dll!System.Windows.Forms.DataGridView.OnRowsAddedInternal(int rowIndex, int rowCount) Line 18629    C#
         System.Windows.Forms.dll!System.Windows.Forms.DataGridViewRowCollection.OnCollectionChanged_PostNotification(System.ComponentModel.CollectionChangeAction cca = Add, int rowIndex = 0, int rowCount, System.Windows.Forms.DataGridViewRow dataGridViewRow = {DataGridViewRow { Index=-1 }}, bool changeIsDeletion = false, bool changeIsInsertion = false, bool recreateNewRow = false, System.Drawing.Point newCurrentCell) Line 2227 + 0x34 bytes    C#
         System.Windows.Forms.dll!System.Windows.Forms.DataGridViewRowCollection.OnCollectionChanged(System.ComponentModel.CollectionChangeEventArgs e, int rowIndex, int rowCount) Line 2058    C#
         System.Windows.Forms.dll!System.Windows.Forms.DataGridViewRowCollection.AddInternal(bool newRow, object[] values) Line 414    C#
         System.Windows.Forms.dll!System.Windows.Forms.DataGridView.AddNewRow(bool createdByEditing = true) Line 77 + 0x20 bytes    C#
         System.Windows.Forms.dll!System.Windows.Forms.DataGridView.OnCurrentCellDirtyStateChanged(System.EventArgs e = {System.EventArgs}) Line 14932 + 0xc bytes    C#
         System.Windows.Forms.dll!System.Windows.Forms.DataGridView.IsCurrentCellDirtyInternal.set(bool value) Line 3574    C#
         System.Windows.Forms.dll!System.Windows.Forms.DataGridView.NotifyCurrentCellDirty(bool dirty = true) Line 10580    C#
         System.Windows.Forms.dll!System.Windows.Forms.DataGridViewComboBoxEditingControl.NotifyDataGridViewOfValueChange() Line 161    C#
         System.Windows.Forms.dll!System.Windows.Forms.DataGridViewComboBoxEditingControl.OnSelectedIndexChanged(System.EventArgs e) Line 171    C#
         System.Windows.Forms.dll!System.Windows.Forms.ComboBox.SelectedIndex.set(int value) Line 1029    C#
         System.Windows.Forms.dll!System.Windows.Forms.ComboBox.InterceptAutoCompleteKeystroke(System.Windows.Forms.Message m) Line 2153    C#
         System.Windows.Forms.dll!System.Windows.Forms.ComboBox.ProcessKeyEventArgs(ref System.Windows.Forms.Message m = {msg=0x100 (WM_KEYDOWN) hwnd=0x460eca wparam=0x2e lparam=0x1530001 result=0x0}) Line 2856 + 0x3f bytes    C#
         System.Windows.Forms.dll!System.Windows.Forms.Control.ProcessKeyMessage(ref System.Windows.Forms.Message m) Line 10332 + 0xc bytes    C#
         System.Windows.Forms.dll!System.Windows.Forms.Control.WmKeyChar(ref System.Windows.Forms.Message m = {msg=0x100 (WM_KEYDOWN) hwnd=0x460eca wparam=0x2e lparam=0x1530001 result=0x0}) Line 12877 + 0xc bytes    C#
         System.Windows.Forms.dll!System.Windows.Forms.Control.WndProc(ref System.Windows.Forms.Message m) Line 13695    C#
         System.Windows.Forms.dll!System.Windows.Forms.ComboBox.WndProc(ref System.Windows.Forms.Message m) Line 3676    C#
         System.Windows.Forms.dll!System.Windows.Forms.Control.ControlNativeWindow.OnMessage(ref System.Windows.Forms.Message m) Line 14051    C#
         System.Windows.Forms.dll!System.Windows.Forms.Control.ControlNativeWindow.WndProc(ref System.Windows.Forms.Message m) Line 14106    C#
         System.Windows.Forms.dll!System.Windows.Forms.NativeWindow.DebuggableCallback(System.IntPtr hWnd, int msg = 256, System.IntPtr wparam, System.IntPtr lparam) Line 777 + 0xa bytes    C#

    Thanks,
    Rong-Chun Zhang
    MSDN Subscriber Support in Forum
    If you have any feedback on our support, please contact msdnmg@microsoft.com

    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Welcome to the All-In-One Code Framework! If you have any feedback, please tell us.
    Friday, August 14, 2009 5:18 AM
  • Hello Michael,

    I am writing to check the status of the issue on your side. Would you mind letting me know the result of the suggestions? If you have any additional question, welcome to post here.

    Have a great day!

    Thanks,
    Rong-Chun Zhang
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Welcome to the All-In-One Code Framework! If you have any feedback, please tell us.
    Monday, August 17, 2009 10:10 AM
  • Rong-Chun,

    Using the workaround that you mentioned (not passing the key-press onto the combo box) we were able to fix the issue.

    Thanks for all your help!

    Michael
    Monday, August 17, 2009 11:51 AM
  • I marked your workaround as the answer but is this not a bug?  It seems to me that if one wanted to perform some action on delete (inside of a control) you could not, with this workaround.
    Monday, August 17, 2009 12:09 PM