1

Here is my code:

foreach (DataGridViewRow r in dgv01.Rows)

if (r.Cells[0].Value.ToString() == abc)

{

dgv01.Rows.Remove(r);

//dgv01.CurrentCell = dgv01.Rows[0].Cells[0]; - **also tried**

}

But only some rows are deleted - not all specified !?

Why - foreach - does not mean - foreach ?

1

5 Answers 5

4

I have to remind you that it is dangerous to use a foreach block when you want to modify/remove the data being traversed. The removal messes up with the index of the foreach iterator.

Solution? Use a reverse for loop instead.

Sign up to request clarification or add additional context in comments.

Comments

2

First of all it is not a good idea to change collection inside foreach loop. Secondly foreach is not behaving how you want because once the first row is removed then second row will become the first row but because in foreach the checking will be done on second row which is actually a third row. so, checking on the second row has been skipped. The best way to do is use for loop in a reverse order.

to know why foreach is not behaving like foreach try this simple example.

 private List<int> list = Enumerable.Range(0, 10).ToList<int>();
 for(int i=0;i<list.Count;++i)
       {
           if (list[i] < 5)
               list.RemoveAt(i);
       }

       list.ForEach(x => Console.Write(x));

Output:
1356789

Comments

2

When you iterate over a collection using foreach, the collection should not be modified otherwise, in the best of scenarios, you end up not covering the entire collection. Most of the time, however, modifying the collection while within a foreach block, the iteration will fail.

In order to remove the rows from the DataGridView, you'll have to use a for iteration block or a two-step process both of which I display below.


for Iteration Block

This procedure uses an index to traverse the collection, modifying the collection as you go. The thing you need to know here is that if you intend to modify the collection, you do not have the index increment (go forward through the collection); you decrement the index (go backwards through the collection). If you modify (remove or add items) the collection while iterating forwards, you may not end up visiting all the items in the collection.

Here is code to remove rows from the DataGridView. Remember, we iterate backwards.

for (int i = dgv01.Rows.Count - 1; i >= 0; i--)
{
    if (dgv01.Rows[i].Cells[0].Value.ToString() == "abc")
    {
        dgv01.Rows.RemoveAt(i);
    }
}


foreach Iteration Block

This procedure uses a two-step approach. The first step finds the items to be removed and the second step removes the items from the collection. This two-step process is necessary for the reasons I explained earlier.

Now the code. Remember, it is a two-step process.

// step 1. find the items to be removed

//items to be removed will be added to this list
var itemsToRemove = new List<DataGridViewRow>(); 
foreach (DataGridViewRow r in dgv01.Rows)
{
    if (r.Cells[0].Value.ToString() == "abc")
    {
        itemsToRemove.Add(r);
    }
}


//step 2. remove the items from the DataGridView
foreach (var r in itemsToRemove)
{
    // this works because we're not iterating over the DataGridView.
    dgv01.Rows.Remove(r);
}


One last thing you should know is that the procedures I have demonstrated here do not apply to the DataGridViewRowCollection class only; it applies to all collections that implement the IList<T> or the ICollection<T> interface. So, yes, the process can be used for Lists, Dictionaries, ControlCollections and all other similar classes.

Comments

1

do a descending sorting on column[0] then from bottom u can delete the rows. Once abc is over u can break the loop also. Other wise u can put a row filter on dataTable u are using.

((DataTable)this.datagrid1.DataSource).DefaultView .RowFilter

Comments

1

Whenever I have to modify a collection inside a foreach I usually make a new collection which I fill with the data I want to modify, and then loop through this second collection to do the actual changes to the main collection. In this way I never modify a collection while looping it, so I avoid the situation described by MChicago.

In your case I usually would write this kind of code:

List<DataGridViewRow> toDel = new List<DataGridViewRow>();
foreach (DataGridViewRow r in dgv01.Rows)    
    if (r.Cells[0].Value.ToString() == "abc")    
        toDel.Add(r);

foreach (DataGridViewRow aRow in toDel)   
    dgv01.Rows.Remove(aRow);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.