0

I am writing a windows forms application in C# in which i am dynamically creating TextBoxes and PictureBoxes with a Panel as the parent:

PictureBox pb = new PictureBox();
pb.Parent = MainPanel;
pb.Name = "pb" + "r" + NumberInRow + "c" + NumberInColumn+ "bi" + buildIndex;
pb.Location = new Point(30 * NumberInRow + 192 * (NumberInRow - 1), 50 * NumberInColumn + 273 * (NumberInColumn - 1));
pb.ImageLocation = ThumbLinks[i];

TextBox tb = new TextBox();
tb.Parent = MainPanel;
tb.Name = "tb" + "r" + NumberInRow + "c" + NumberInColumn + "bi" + buildIndex;
tb.Location = new Point(pb.Location.X - 4, pb.Location.Y + pb.Size.Height + 5);
tb.Text = GalleryNames[i];

I am trying to delete them with this:

foreach (PictureBox pb in MainPanel.Controls)
    {
                MainPanel.Controls.Remove(pb);
    }

foreach (TextBox tb in MainPanel.Controls)
     {
                MainPanel.Controls.Remove(tb);
     }

This only seems to work once though. Visual Studio tells me that it can't convert System.Windows.Forms.TextBox into System.Windows.Forms.PictureBox.

Is there any way to delete the PictureBoxes and TextBoxes differently?

I've read about something like MainPanel.Children.Remove(); but it doesn't seem to exist or i am doing something wrong.

  • the error you're getting is because the element's type inside the Panel are PictureBox and TextBox, so you can't use a Foreach and cast all of them as PictureBox/TextBox. Besides if remove items from list in a Foreach loop it wont work correctly. If you want to remove all of them then use `while (MainPanel.Controls.Count > 0) MainPanel.Controls.RemoveAt(0);`. I hope it helps. – denys-vega Sep 24 '18 at 18:45
  • Yeah, removing all of them works for my application. Thanks :) – ShiranaiDev Sep 24 '18 at 18:52

2 Answers2

0
foreach (var control in MainPanel.Controls
                        .Where(c => c is PictureBox) || c is TextBox)
{
     MainPanel.Controls.Remove(control);
}

This will remove each item of types, both PictureBox and TextBox. The issue with this code of course is that you are modifying an collection whilst enumerating it.

One approach to resolving this issue could be to build a collection of controls to remove first

var controls = MainPanel.Controls.Where(c => c is PictureBox || c is TextBox).ToList();

And then to enumerate that collection removing each item from the Panel.

foreach (var toRemove in controls)
     MainPanel.Controls.Remove(toRemove);

It would further benefit one to make sure that the item is removed from the UI on the correct thread

delegate void RemoveControlDelegate(Control controlToRemove);

private void RemoveControl(Control control)
{
   if (InvokeRequired)
   {
       BeginInvoke(new RemoveControlDelegate(RemoveControl), control);
   }
   else
   {
       MainPanel.Controls.Remove(control);
   }
}

foreach (var toRemove in controls)
     RemoveControl(toRemove);
-1

Look at MainPanel.Controls.OfType<PictureBox>() and MainPanel.Controls.OfType<TextBox>(). You can use this in conjunction with a .ToList() call to avoid modifying an interator while it's still active:

var PBs = MainPanel.Controls.OfType<PictureBox>().ToList();
var TBs = MainPanel.Controls.OfType<TextBox>().ToList();
foreach (var pb in PBs)
{
    MainPanel.Controls.Remove(pb);
}
foreach (TextBox tb in TBs)
{
    MainPanel.Controls.Remove(tb);
}
Joel Coehoorn
  • 399,467
  • 113
  • 570
  • 794