2

foreachY 軸上の同じポイントにあるすべてのコントロールを取り除くために使用しているボタン クリック イベント ハンドラー内にループがあります。行を追加するコントロールがあり、追加するつもりのない行を削除するオプションがユーザーに必要です。

ループを単独で使用するforeachと、一貫して 2 つの項目が失われます。毎回同じ 2 つの項目です。Y 値が実際に同一であることを確認しました。関数を実行し続けると、3 回実行した後に行のすべてのコントロールが削除されます。foreachただし、すべて同じ値を使用してループをネストすると、機能します。以下のコードを参照してください。

これはかなりずさんな方法のように思えますが、私にとってはうまくいった唯一の解決策でもあります。ループ内で 2 番目の変数 (つまり、) を宣言するように言った他の投稿をいくつか見ましたControl z = c; if(z.Location....)。ここでの動作に違いはありませんでした。foreachループ自体が機能しない理由を誰か説明できますか? 繰り返しネストせずに修正するにはどうすればよいですか?

働く:

    internal void MinButt_Click(object sender, EventArgs e)
    {
        Scratch.tScratch.panel2.Controls.RemoveByKey("Record" + arrDynamY[0].ToString());
        foreach (Control c in Scratch.tScratch.panel2.Controls)
        {
            if (c.Location.Y == arrDynamY[1])
            {
                c.Dispose();
            }

            foreach (Control ctrl in Scratch.tScratch.panel2.Controls)
            {
                if (ctrl.Location.Y == arrDynamY[1])
                {
                    ctrl.Dispose();
                }
            }
        }
    }

毎回同じ 2 つのコントロールを見逃します。

    internal void MinButt_Click(object sender, EventArgs e)
    {
        Scratch.tScratch.panel2.Controls.RemoveByKey("Record" + arrDynamY[0].ToString());
        foreach (Control c in Scratch.tScratch.panel2.Controls)
        {
            if (c.Location.Y == arrDynamY[1])
            {
                c.Dispose();
            }
        }
    }
4

4 に答える 4

3

最初に削除するためのコントロールを取得し、後で次のように削除する必要があります。

var controlsToRemove = from Control c in Scratch.tScratch.panel2.Controls
                       where c.Location.Y == arrDynamY[1]
                       select c;

foreach (var c in controlsToRemove.ToArray())
{
    Scratch.tScratch.panel2.Controls.Remove(c);
    c.Dispose();
}
于 2013-02-20T06:52:57.690 に答える
1

反復しているコレクションのアイテムを変更(この場合は破棄)しています。これが予期しない動作の原因だと思います。forループを使用してこの問題を回避できます。

        for (int i = Scratch.tScratch.panel2.Controls.Length - 1; i >= 0; i-- )
            if (Scratch.tScratch.panel2.Controls[i].Location.Y == arrDynamY[1])
                Scratch.tScratch.panel2.Controls[i].Dispose();

Scratch.tScratch.panel2.Controls配列としてアクセスできると思いました。

于 2013-02-20T06:52:28.290 に答える
0

別のループで破棄を行うと、他のコントロールに影響を与える可能性があります

これを試して

internal void MinButt_Click(object sender, EventArgs e)
{
    Scratch.tScratch.panel2.Controls.RemoveByKey("Record" + arrDynamY[0].ToString());
    var controlsToDispose = new List<Control>();
    foreach (Control c in Scratch.tScratch.panel2.Controls)
    {
        if (c.Location.Y == arrDynamY[1])
        {
            controlsToDispose.Add(c);
        }
    }
    foreach (Control c in controlsToDispose )
    {
        c.Dispose();
    }              
}
于 2013-02-20T06:47:16.370 に答える
-1

これは、コントロールで Dispose() を呼び出すと、GC が開始されるまでメモリにとどまるためです。以下を試してください。

List<Control> controlsToDispose = new List<Control>();
foreach (Control c in Scratch.tScratch.panel2.Controls)
{
       if (c.Location.Y == arrDynamY[1])
       {
           controlsToDispose.Add(c);
           c.Dispose();
       }
}
while(controlsToDispose.Count>0)
{
      Control ctrl = controlsToDispose[0];
      controlsToDispose.RemoveAt(0);
      ctrl.Dispose();
}
于 2013-02-20T06:59:08.477 に答える