Home > Software engineering >  Panel.Controls.Remove not deleting all the controls It should(.NET)
Panel.Controls.Remove not deleting all the controls It should(.NET)

Time:01-15

I'm making a database manager program and the program creates only as much textbox as needed (counts the columns in the table). But for some reason the program is not removing all the textboxes I want. New textboxes should be created and old ones should be removed on every "ComboBoxSelectedIndexChange".

Here is my code snippet:

var elm = panel20.Controls.OfType<System.Windows.Forms.TextBox>();
foreach (var item in elm)
{
    DeleteControlsWithTag(item.Tag.ToString());
}
               
button19.Enabled = true;
one_cond = string.Empty;
if (comboBox19.Text != string.Empty)
{
    one_cond = comboBox19.Text.ToUpper();
    if (one_cond == "ÖSSZES")
    {
         string allcolumn = "(";
         colnames.Remove("Összes");
         for (int i = 0; i < colnames.Count - 1; i  )
         {
             allcolumn  = colnames.ElementAt(i)   ",";
         }
         allcolumn  = colnames.Last()   ")";
    
         button19.Enabled = false;
    
         textBox16.Text = ManualQuery   " "   from   " "   allcolumn   " "   "VALUES"   " ";
                       
         if (3 < colnames.Count)
         {
              for (int i = 0; i < colnames.Count; i  )
              {
                  System.Windows.Forms.TextBox textbox = new System.Windows.Forms.TextBox();
                                
                  textbox.Name = $"textbox_{i}";
                  textbox.AccessibleName = $"textbox_{i}";
                  textbox.Tag = $"textbox_{i}";
                  panel20.Controls.Add(textbox);
                  textbox.Parent = panel20;
                  //"textbox_"   colnames[i]   i
                  if (2<i)
                  {
                      if (i == 3)
                      {
                          textbox.Location = new System.Drawing.Point(489, 49);
                      }
                      else
                      {
                          textbox.Location = new System.Drawing.Point(489   ((i - 3) * 71), 49);
                      }
                  }
                  else
                  {
                      if (0 < i)
                      {
                          textbox.Location = new System.Drawing.Point(467   (i * 71), 17);
                      }
                      else
                      {
                          textbox.Location = new System.Drawing.Point(467, 17);
                      }
                  }
                                
    
                  textbox.Size = new System.Drawing.Size(64, 20);
              }
          }
          else
          {
              for (int i = 0; i < colnames.Count; i  )
              {
                  System.Windows.Forms.TextBox textbox = new System.Windows.Forms.TextBox();
                               
                  textbox.Name = $"textbox_{i}";
                  textbox.AccessibleName = $"textbox_{i}";
                  textbox.Parent = panel20;
                  panel20.Controls.Add(textbox);
                  textbox.Tag = $"textbox_{i}";
                  if (0<i)
                  {
                      textbox.Location = new System.Drawing.Point(467   (i*71), 17);
                  }
                  else
                  {
                      textbox.Location = new System.Drawing.Point(467, 17);
                  }
                               
                  textbox.Size = new System.Drawing.Size(64, 20);
              }
           }
       }
       else
       {
            onecondinsert = "("   one_cond   ")";
            textBox16.Text = ManualQuery   " "   from   " "   onecondinsert   " "   "VALUES"   " ";
                        
            System.Windows.Forms.TextBox textbox = new System.Windows.Forms.TextBox();
            textbox.Name = $"textbox";
            textbox.AccessibleName = $"textbox";
            textbox.Location = new System.Drawing.Point(464, 20);
            textbox.Size = new System.Drawing.Size(100, 20);
            textbox.Parent = panel20;
            textbox.Tag = "textbox";
            panel20.Controls.Add(textbox);
            //tbox.TextChanged  = tbox_TextChanged;
        }
    }
               
    MessageBox.Show(elm.Count().ToString());
}

and here is some screenshot of how the problem looks like

on the first select it works

on this picture you can see the program did not delete all the text box. longer textbox is the new one

On the third picture I selected another column (only one textbox should be visible) but the program deletes one textbox as you can see here

After the third selection it deletes the last extra textbox too 3. try it "works"

I have tried different ways to delete from the panel20.controls but all produced the same bug

Hope someone can help me, Thanks

Update: I tried another method from here: C#, deleting all the controls with the same .Tag

private List<Control> GetTaggedControls(string tag, Control parent)
{
    var taggedControls = new List<Control>();
    foreach (Control control in parent.Controls)
    {
        if (control.Tag?.ToString() == tag)
        {
            taggedControls.Add(control);
        }
    
        // Recursively call this method in case this is a container
        taggedControls.AddRange(GetTaggedControls(tag, control));
    }
    
    return taggedControls;
}
    
// Deletes all controls with the specified tag
private void DeleteControlsWithTag(string tag)
{
    foreach (Control control in GetTaggedControls(tag, this))
    {
        panel20.Controls.Remove(control);
    }
}

and I tried to delete the textboxes like this:

var elm = panel20.Controls.OfType<System.Windows.Forms.TextBox>();
foreach (var item in elm)
{
    DeleteControlsWithTag(item.Tag.ToString());
}

but it is still not working

CodePudding user response:

Your GetTaggedControls() function is finding ANY type of control, RECURSIVELY starting at the main Form container level, that has a specific tag. So returned controls might not be from many containers, but your DeleteControlsWithTag() method tries to remove all matches only from panel20. That may or may not be a problem; it's unclear from the pictures and possibly incomplete posted code.

When you say remove the old textboxes, can we simply remove ALL existing TextBoxes, or do you really need to match tags?

From your original attempt:

var elm = panel20.Controls.OfType<System.Windows.Forms.TextBox>();
foreach (var item in elm)
{
    DeleteControlsWithTag(item.Tag.ToString());
}

This is finding ALL textboxes in panel20, then trying to delete them based on matching tags with the helper function. So the tag doesn't even matter since you are finding all textboxes to begin with...

Just try removing all TextBoxes from panel20?

var elm = panel20.Controls.OfType<System.Windows.Forms.TextBox>().ToList();
elm.ForEach(tb => panel20.Controls.Remove(tb));

CodePudding user response:

Okay, now I tried to tie together Idle_Mind's and LarsTech's recommendation and finally it's working fine with "Dispose".

Thanks guys for your quick help.

here is the previous code:

var elm = panel20.Controls.OfType<System.Windows.Forms.TextBox>();
foreach (var item in elm)
{
    DeleteControlsWithTag(item.Tag.ToString());
}

and here is the new one:

var elm = panel20.Controls.OfType<System.Windows.Forms.TextBox>().ToList();
            elm.ForEach(tb => tb.Dispose());
  • Related