C#,删除所有具有相同 .Tag 的控件
C#, deleting all the controls with the same .Tag
我的问题是,当我比较两个完全相同的标签时,结果发现它们是不同的。
代码描述:我创建了 3 个控件(按钮、标签和文本框)并为它们分配了相同的标签(假设为 0)。当我按下这个新创建的按钮时,我想删除所有具有相同标签的 3 个控件。
添加按钮的代码(简化):
int Count = 0; // This var changes, but for the example it is 0
Button newButton = new Button();
newButton.Tag = Count;
newButton.Click += new EventHandler(DeleteName);
Controls.Add(newButton);
Label newLabel = new Label();
newLabel.Tag = Count;
Controls.Add(newLabel);
TextBox 也一样。
删除背后的编码:
private void DeleteName(object sender, EventArgs e)
{
List<Control> toDelete = new List<Control>();
Button btn = sender as Button;
foreach (Control c in Controls)
{
if (c.Tag == btn.Tag)
toDelete.Add(c);
}
int tmp = toDelete.Count;
for (int i = 0; i < tmp; i++)
{
Controls.Remove(toDelete[i]);
}
}
当我以前执行相同的逻辑时它曾经完美地工作,但现在它只删除了按钮而没有其他控件(文本框和标签保持不变)。例如,当我将 "if (c.Tag == btn.Tag)" 替换为 "if (c is TextBox)" 时,它会将所有文本框添加到列表中并删除它们,因此我认为问题出在标签比较中。
您 运行 的可能原因是 Tag
是一个 object
,因此相等比较将进行引用比较,但您将其设置为一个值类型。即使您将其设置为引用类型,如果它们指向完全相同的对象,则比较只会 return true
。
解决此问题的一种方法是将 Tag
转换为适当的类型,或者更常见的是,使用 ToString()
方法进行比较。我们还应该在检查中添加空条件运算符,以防 Tag
为空,以避免 NullReferenceException
:
if (c.Tag?.ToString() == btn.Tag?.ToString())
您可能考虑做的另一件事是创建一个单独的方法来删除具有特定标记的所有控件,以及另一个递归地查找具有该标记的所有控件的方法。如果您有一些带有 "delete" 标签的控件是不同容器的子项,这将有所帮助。
例如:
// Returns all controls under the parent with the specified 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))
{
Controls.Remove(control);
}
}
例如,如果您将下面的代码添加到一个新的 WinForm
项目中,它将创建 10 个标签,每隔一个标签包含一个 Tag
和 "deleteMe"
。它还会创建一个按钮,单击该按钮会调用上面的 DeleteControlsWithTag
方法:
private void Form1_Load(object sender, EventArgs e)
{
var padSpace = 5;
var height = 15;
// Add 10 labels, with a common tag on every other one
for (int i = 0; i < 10; i++)
{
Controls.Add(new Label
{
Text = $"Label {i}",
Top = padSpace * (i + 1) + height * i,
Height = height,
Visible = true,
Tag = i % 2 == 0 ? "deleteMe" : "saveMe"
});
}
// Add a button that will delete controls with deleteMe tag
var btn = new Button
{
Text = "Delete Even Labels",
Height = 20,
Width = 150,
Top = padSpace * 11 + height * 10,
Visible = true
};
btn.Click += (o, ea) => { DeleteControlsWithTag("deleteMe"); };
Controls.Add(btn);
}
我的问题是,当我比较两个完全相同的标签时,结果发现它们是不同的。
代码描述:我创建了 3 个控件(按钮、标签和文本框)并为它们分配了相同的标签(假设为 0)。当我按下这个新创建的按钮时,我想删除所有具有相同标签的 3 个控件。
添加按钮的代码(简化):
int Count = 0; // This var changes, but for the example it is 0
Button newButton = new Button();
newButton.Tag = Count;
newButton.Click += new EventHandler(DeleteName);
Controls.Add(newButton);
Label newLabel = new Label();
newLabel.Tag = Count;
Controls.Add(newLabel);
TextBox 也一样。
删除背后的编码:
private void DeleteName(object sender, EventArgs e)
{
List<Control> toDelete = new List<Control>();
Button btn = sender as Button;
foreach (Control c in Controls)
{
if (c.Tag == btn.Tag)
toDelete.Add(c);
}
int tmp = toDelete.Count;
for (int i = 0; i < tmp; i++)
{
Controls.Remove(toDelete[i]);
}
}
当我以前执行相同的逻辑时它曾经完美地工作,但现在它只删除了按钮而没有其他控件(文本框和标签保持不变)。例如,当我将 "if (c.Tag == btn.Tag)" 替换为 "if (c is TextBox)" 时,它会将所有文本框添加到列表中并删除它们,因此我认为问题出在标签比较中。
您 运行 的可能原因是 Tag
是一个 object
,因此相等比较将进行引用比较,但您将其设置为一个值类型。即使您将其设置为引用类型,如果它们指向完全相同的对象,则比较只会 return true
。
解决此问题的一种方法是将 Tag
转换为适当的类型,或者更常见的是,使用 ToString()
方法进行比较。我们还应该在检查中添加空条件运算符,以防 Tag
为空,以避免 NullReferenceException
:
if (c.Tag?.ToString() == btn.Tag?.ToString())
您可能考虑做的另一件事是创建一个单独的方法来删除具有特定标记的所有控件,以及另一个递归地查找具有该标记的所有控件的方法。如果您有一些带有 "delete" 标签的控件是不同容器的子项,这将有所帮助。
例如:
// Returns all controls under the parent with the specified 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))
{
Controls.Remove(control);
}
}
例如,如果您将下面的代码添加到一个新的 WinForm
项目中,它将创建 10 个标签,每隔一个标签包含一个 Tag
和 "deleteMe"
。它还会创建一个按钮,单击该按钮会调用上面的 DeleteControlsWithTag
方法:
private void Form1_Load(object sender, EventArgs e)
{
var padSpace = 5;
var height = 15;
// Add 10 labels, with a common tag on every other one
for (int i = 0; i < 10; i++)
{
Controls.Add(new Label
{
Text = $"Label {i}",
Top = padSpace * (i + 1) + height * i,
Height = height,
Visible = true,
Tag = i % 2 == 0 ? "deleteMe" : "saveMe"
});
}
// Add a button that will delete controls with deleteMe tag
var btn = new Button
{
Text = "Delete Even Labels",
Height = 20,
Width = 150,
Top = padSpace * 11 + height * 10,
Visible = true
};
btn.Click += (o, ea) => { DeleteControlsWithTag("deleteMe"); };
Controls.Add(btn);
}