0

i have windows form which have a button, when button is clicked it dynamically generated controls, also a button which is dynamically generated is added so that it will remove the controls which are in line, means aside the button, a row of control will be removed when button clicked my code is

int c = 0;
        private void button1_Click(object sender, EventArgs e)
        {
            int v;
            v = c++;
            panel1.VerticalScroll.Value = VerticalScroll.Minimum;

            Button btn = new Button();
            btn.Name = "btn" + v;
            btn.Text = "Remove";
            btn.Location = new Point(750, 5 + (30 * v));
            btn.Click += new EventHandler(btn_Click);

            ComboBox combo = new ComboBox();
            combo.Name = "combobox" + v;
            combo.Location = new Point(30, 5 + (30 * v));
            combo.Tag = btn;

            ComboBox combo2 = new ComboBox();
            combo2.Name = "combobox2" + v;
            combo2.Location = new Point(170, 5 + (30 * v));
            combo2.Tag = btn;

            TextBox txt = new TextBox();
            txt.Name = "txtbx" + v;
            txt.Location = new Point(300, 5 + (30 * v));
            txt.Tag = btn;

            TextBox txt2 = new TextBox();
            txt2.Name = "txtbx2" + v;
            txt2.Location = new Point(450, 5 + (30 * v));
            txt2.Tag = btn;

            TextBox txt3 = new TextBox();
            txt3.Name = "txtbx3" + v;
            txt3.Location = new Point(600, 5 + (30 * v));
            txt3.Tag = btn;

            panel1.Controls.Add(combo);
            panel1.Controls.Add(btn);
            panel1.Controls.Add(txt);
            panel1.Controls.Add(combo2);
            panel1.Controls.Add(txt2);
            panel1.Controls.Add(txt3);   
        }
        private void btn_Click(object sender, EventArgs e)// this is the dynamically added button's event which will remove the combobox and textbox
        {
            Button btnh = sender as Button;
            foreach (Control item in panel1.Controls.OfType<TextBox>())
            {
                if (item.Tag == sender || item == sender)
                    panel1.Controls.Remove(item);
            }
            foreach (Control item in panel1.Controls.OfType<ComboBox>())
            {
                if (item.Tag == sender || item == sender)
                    panel1.Controls.Remove(item);
            }
            panel1.Controls.Remove(btnh);
        }

my error is nothing but the problem is it dosnt removes all the controls it leaves controls and i dont know whats the problem my code is simple and easy but i dont know where it lacks

8
  • Is this execution only in C# or are you doing any interop?
    – bonCodigo
    Commented Dec 15, 2012 at 19:58
  • Take a look at this MSDN Link 'Control.Tag Property'-msdn.microsoft.com/en-us/library/…
    – MethodMan
    Commented Dec 15, 2012 at 20:00
  • i am working in windows form i dont know about others, sorry my english is not so good, if i misunderstood you Commented Dec 15, 2012 at 20:00
  • @DJKRAZE i am binding the object to other object so that it can be removed, Commented Dec 15, 2012 at 20:03
  • Ok just wanted to get a clearer understanding on where your train of though was.. thanks
    – MethodMan
    Commented Dec 15, 2012 at 20:04

2 Answers 2

3

The problem is that you are removing items while you are looping through the collection. The foreach-statement might skip items in that case. Store the items to be removed in a list first:

List<Control> toBeRemoved = panel1.Controls
    .Cast<Control>()
    .Where(c => c.Tag == sender)
    .ToList();
foreach (Control c in toBeRemoved) {
    panel1.Controls.Remove(c);
}

You can also remove in a loop easily, if you loop backwards:

for (int i = panel1.Controls.Count - 1; i >= 0; i--) {
    if (panel1.Controls[i].Tag == sender) {
        panel1.Controls.RemoveAt(i);
    }
}
5
  • thanks but i will really appreciate if you will explain what is this List<Control> toBeRemoved = panel1.Controls.Cast<Control>().Where(c => c.Tag == sender).ToList(); i know that is a list but what is where C => and that all things,i have seen this first time is there any other solution for this problem? Commented Dec 15, 2012 at 20:12
  • and your solutions is only for the removing of sender then how the tag which are related to sender are removed? can you explain sir, Commented Dec 15, 2012 at 20:18
  • Well, this is a LINQ (Language INtegrated Query). The Controls collection does not implement IEnumerable<T> but LINQ the source to be one. So Cast<Control> converts the Controls collection to an IEnumerable<Control>. Then the Where clause selects controls whose Tag is equal to the sender (the button). And finally a list is created with the result. The expression c => c.Tag == sender is a lambda expression. You can think of it like a very concise way of writing a function method. The Where clause uses this function to test the items of the enumeration. Commented Dec 15, 2012 at 20:20
  • My solution removes controls whose Tag is equal to the sender, but does not remove the sender itself. Commented Dec 15, 2012 at 20:21
3

Removing items in a foreach loop often leads to issues with the list changing while you're traversing it.

This linq should do the trick:

private void btn_Click(object sender, EventArgs e)// this is the dynamically added button's event which will remove the combobox and textbox
    {
        Button btnh = sender as Button;
        panel1.Controls.OfType<TextBox>().Where(i => i.Tag == sender || i == sender).ToList().ForEach(i => panel1.Controls.Remove(i));
        panel1.Controls.OfType<ComboBox>().Where(i => i.Tag == sender || i == sender).ToList().ForEach(i => panel1.Controls.Remove(i));

        panel1.Controls.Remove(btnh);
    }

Why the linq foreach works I'm not sure though :)

2
  • 1
    You're welcome. I would think the reason why this works is because ToList() creates a temporary list, but again I'm not entirely sure.
    – JGaarsdal
    Commented Dec 15, 2012 at 20:35
  • @JGaarsdal, yes, after the ToList() you are working on a temporary list (the IL creates a local variable), and and you remove items from the other list. Thats why its working. Your guess is correct.
    – Mafii
    Commented May 25, 2016 at 14:34

Not the answer you're looking for? Browse other questions tagged or ask your own question.