1

これが私のコードです:

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

}

しかし、一部の行のみが削除されます - すべてが指定されているわけではありません!?

なぜ - foreach - は - foreachを意味しないのですか?

4

5 に答える 5

4

トラバースされるデータを変更/削除する場合、foreachブロックを使用するのは危険であることを忘れないでください。削除は、foreachイテレータのインデックスを台無しにします。

解決?代わりに、逆forループを使用してください。

于 2012-05-25T04:22:26.630 に答える
2

を使用してコレクションを反復処理する場合、コレクションをforeach変更しないでください。最良のシナリオでは、コレクション全体をカバーすることはありません。ただし、ほとんどの場合、foreachブロック内でコレクションを変更すると、反復は失敗します。

DataGridView から行を削除するには、for反復ブロックまたは 2 段階のプロセスを使用する必要があります。その両方を以下に示します。


for反復ブロック

この手順では、インデックスを使用してコレクションをトラバースし、コレクションを変更します。ここで知っておく必要があるのは、コレクションを変更する場合は、インデックスの増分がない (コレクションを進む) ということです。インデックスをデクリメントします (コレクションをさかのぼります)。前方への反復中にコレクションを変更 (アイテムの削除または追加) すると、コレクション内のすべてのアイテムにアクセスできない場合があります。

DataGridView から行を削除するコードを次に示します。覚えておいてください、後方に繰り返します。

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


foreach反復ブロック

この手順では、2 段階のアプローチを使用します。最初のステップで削除するアイテムを見つけ、2 番目のステップでコレクションからアイテムを削除します。この 2 段階のプロセスは、先ほど説明した理由から必要です。

今コード。これは2 段階のプロセスであることを忘れないでください。

// 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);
}


最後に 1 つ知っておくべきことは、ここで説明した手順はDataGridViewRowCollectionクラスだけに適用されるわけではないということです。IList<T>またはICollection<T>インターフェイスを実装するすべてのコレクションに適用されます。そうです、このプロセスは、List、Dictionaries、ControlCollection、およびその他すべての同様のクラスに使用できます。

于 2012-05-25T05:53:38.460 に答える
2

まず、foreach ループ内でコレクションを変更することはお勧めできません。第 2 に、最初の行が削除されると 2 行目が最初の行になるため、foreach は希望どおりに動作しませんが、foreach では実際には 3 行目である 2 行目でチェックが行われるためです。そのため、2 行目のチェックはスキップされました。最善の方法は、for ループを逆の順序で使用することです。

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

出力:
1356789

于 2012-05-25T04:35:50.727 に答える
1

column [0]で降順の並べ替えを実行すると、下からuで行を削除できます。abcが終了すると、uもループを中断できます。それ以外の場合は、uが使用しているdataTableに行フィルターを配置できます。

((DataTable)this.datagrid1.DataSource).DefaultView .RowFilter
于 2012-05-25T04:26:54.120 に答える
1

foreach 内のコレクションを変更する必要がある場合は常に、変更するデータを入力する新しいコレクションを作成し、この 2 番目のコレクションをループしてメイン コレクションに実際の変更を加えます。このようにして、ループ中にコレクションを変更することは決してないので、MChicago で説明されている状況を回避できます。

あなたの場合、私は通常この種のコードを書きます:

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);
于 2012-05-25T04:42:44.113 に答える