简体   繁体   English

c#winform-如何删除多个DataGridViewRows

[英]c# winform - how to delete multiple DataGridViewRows

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 ? 为什么-foreach-不意味着-foreach

I have to remind you that it is dangerous to use a foreach block when you want to modify/remove the data being traversed. 我必须提醒您,要修改/删除要遍历的数据时,使用foreach块很危险。 The removal messes up with the index of the foreach iterator. 删除与foreach迭代器的索引搞混了。

Solution? 解? Use a reverse for loop instead. 请使用反向for循环。

First of all it is not a good idea to change collection inside foreach loop. 首先,在foreach循环中更改集合不是一个好主意。 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. 其次,foreach表现不理想,因为一旦删除了第一行,第二行便成为第一行,但是因为在foreach中,检查将在第二行进行,而第二行实际上是第三行。 so, checking on the second row has been skipped. 因此,第二行的检查已被跳过。 The best way to do is use for loop in a reverse order. 最好的方法是反向使用for循环。

to know why foreach is not behaving like foreach try this simple example. 要知道为什么foreach不能像foreach那样运行,请尝试以下简单示例。

 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 1356789

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. 当使用foreach遍历一个集合时,否则不应修改该集合,否则,在最佳情况下,最终您将无法覆盖整个集合。 Most of the time, however, modifying the collection while within a foreach block, the iteration will fail. 但是,大多数情况下,在foreach块中修改集合时,迭代将失败。

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. 为了从DataGridView中删除行,您将必须使用for迭代块或两步过程,我将在下面分别显示这两个过程。


for Iteration Block for迭代块

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. 这是从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 foreach迭代块

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; 您应该知道的最后一件事是,我在此处演示的过程仅适用于DataGridViewRowCollection类; it applies to all collections that implement the IList<T> or the ICollection<T> interface. 它适用于实现IList<T>ICollection<T>接口的所有集合。 So, yes, the process can be used for Lists, Dictionaries, ControlCollections and all other similar classes. 因此,可以,该过程可用于列表,字典,ControlCollection和所有其他类似的类。

do a descending sorting on column[0] then from bottom u can delete the rows. 对column [0]进行降序排序,然后您可以从底部删除行。 Once abc is over u can break the loop also. 一旦abc结束,您也可以打破循环。 Other wise u can put a row filter on dataTable u are using. 否则,您可以在所使用的dataTable上放置行过滤器。

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

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. 每当需要在foreach中修改集合时,通常会创建一个新集合,并用要修改的数据填充该集合,然后遍历第二个集合以对主集合进行实际更改。 In this way I never modify a collection while looping it, so I avoid the situation described by MChicago. 这样,我就不会在循环时修改集合,因此避免了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);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM