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