1

I'm having a simple DataGridView that uses the table Orders(OrderID,CustomerID,ShipName) from the northwind database.After the initial load, i'm adding a new column to each row with a checkbox on it. Now my UI looks like this.

Code for adding the extra column with the checkbox.

DataGridViewCheckBoxColumn checkColumn = new DataGridViewCheckBoxColumn();
checkColumn.Name = "Delete";
checkColumn.HeaderText = "Delete";
checkColumn.Width = 50;
checkColumn.ReadOnly = false;
dataGridView1.Columns.Add(checkColumn);

Also, i have a button called delete which on click ,should delete all rows with the checkbox ticked.

for (int i = dataGridView1.Rows.Count-1; i >=0 ; i--)
{
    DataGridViewRow row = dataGridView1.Rows[i];
    bool isChecked = dataGridView1[3, i].Value != null && (bool)dataGridView1[3, i].Value != false;
    if (isChecked)
    {
        dataGridView1.Rows.RemoveAt(i);
    }
}

However, everytime i click some checkboxes and then the button delete, the last one clicked always isn't deleted.

After some debugging , i found that if i click some checkboxes, then click anywhere else in the UI, and then on the button delete it works as intended.

So, is this a known bug? Am i doing something wrong?

UPDATE

Added a counter to the delete method so i can count how many checkboxes are ticked and procceed to another test:

1: I clicked on the first two checkboxes and then the button delete.The first row was deleted, the counter was 1.

2: I clicked on the first two checkboxes and then outside on a empty space of UI, and then the button delete.Both ticked rows were deleted.The counter was 2.

So the problem is that visually the checkboxes are ticked, but in the code the last one is not unless i change my focus.

Alator
  • 497
  • 6
  • 23
  • you can listen to datagrid checkbox click and add the selected row to a 'DeleteList'. On `Delete` button click, all the items from the `DeleteList` can be removed from the original datagrid collection. – user1579234 Jan 25 '19 at 14:29
  • I have thinked of that workaround but am i doing anything wrong with my current solution? – Alator Jan 25 '19 at 14:38
  • You can use `(bool)dataGridView1[3, i].Value` in your isChecked. Not sure if this will make any difference, but checking `someBool !=false` is same as `someBool` – user1579234 Jan 25 '19 at 14:46
  • I updated my question with more info – Alator Jan 25 '19 at 15:02
  • Perhaps adding an Update() would do the trick, just set an event for cellvaluechanged with the update method – nalnpir Jan 25 '19 at 15:12
  • 1
    Note that there is a big difference between deleting a row and removing it. – Ňɏssa Pøngjǣrdenlarp Jan 25 '19 at 16:19
  • Possible duplicate of [How to Stop DataGridView editing after checked cell?](https://stackoverflow.com/questions/43530300/how-to-stop-datagridview-editing-after-checked-cell) – OhBeWise Jan 25 '19 at 21:54
  • I am guessing something else is going on. I “copy/paste” the posted code and could NOT reproduce the issue you describe. As you commented… _”everytime i click some checkboxes and then the button delete, the last one clicked always isn't deleted.”_ … this did not happen in my varied tests, all rows were “always” properly deleted. – JohnG Jan 26 '19 at 04:57
  • In addition, clicking anywhere else in the UI, another button, another row… clicking anywhere made no difference, all rows were properly deleted when the delete button was clicked. Again, I am guessing that, something else may be going on. How is the data read into the grid? – JohnG Jan 26 '19 at 04:57

3 Answers3

0
foreach (DataGridViewRow row in dataGridView1.Rows)
{
     if (Convert.ToBoolean(row.Cells[3].Value)) //Column Delete
     {
          // what you want to do
     }
}

You've forgotten to convert the value to boolean by using Convert.ToBoolean()

Fatihi Youssef
  • 411
  • 1
  • 6
  • 15
0

May i suggest you change your approach? im thinking that for loop may not be working as intended

        List<int> indexesToDelete = new List<int>();
        dgv.Rows.Cast<DataGridViewRow>().ToList().ForEach(x =>
        {
            if (x.Cells[3].Value != null && (bool)x.Cells[3].Value != false)
            {
                indexesToDelete.Add(x.Index);
            };
        });
        indexesToDelete.Reverse();
        indexesToDelete.ForEach(i => dgv.Rows.RemoveAt(i));

if you wish to continue with your approach i would suggest instead of using removeAt use remove and give the row instead of the index

nalnpir
  • 1,167
  • 6
  • 14
  • I've done nummerous tests about my loop and it is good. I updated my question with more info. – Alator Jan 25 '19 at 15:02
0

How about an event handler for when any cell is clicked on, then tie it to the column name/number then remove the index:

   private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)
    {
        if (e.ColumnIndex == 3)
        {

/* any aditional verifications, can be added, then remove from the index selected */

            dataGridView1.Rows.RemoveAt(e.RowIndex);
        }
    }
need2lease
  • 136
  • 1
  • 2
  • 10