【问题标题】:C#, deleting all the controls with the same .TagC#,删除所有具有相同 .Tag 的控件
【发布时间】:2018-04-13 23:37:21
【问题描述】:

我的问题是,当我比较两个完全相同的标签时,结果却是不同的。

代码描述:我创建了 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);

对于文本框也是如此。

删除背后的编码:

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 is TextBox)”替换“if (c.Tag == btn.Tag)”时,它会将所有 TextBoxes 添加到列表中并删除它们,所以我相信问题出在这个标签的比较。

【问题讨论】:

  • 从“它曾经完美运行”到“现在”之间发生了什么变化?您是否将一堆控件放在另一个容器控件中?如果是这样,您需要单独查询。您是否确认您希望删除的其他控件与您按下以触发此事件的按钮具有相同的标签?
  • 在我不小心删除了整个方法并不得不完全重写之前,它曾经完美地工作过。我没有将控件添加到任何容器中。是的,我用一个消息框检查了所有这些控件都有一个标签“0”,完全一样。
  • 您说“代码的描述:我创建 3 个控件...”但您没有创建任何控件。您是先手动添加它们吗?
  • 我没有包含将控件添加到主题的代码。我使用以下逻辑:Count = 0;按钮 newButton = new Button(); newButton.Tag = 计数; Controls.Add(newButton);标签新标签 = 新标签(); newLabel.Tag = 计数;控件。添加(新标签);文本框也是如此
  • 我建议您单步调试代码,看看为btn.Tagc.Tag 设置了哪些值。

标签: c# winforms controls


【解决方案1】:

您遇到此问题的可能原因是Tagobject,因此相等比较将进行引用比较,但您将其设置为值类型。即使您将其设置为引用类型,如果它们指向完全相同的对象,比较也只会返回 true

解决此问题的一种方法是将Tag 转换为适当的类型,或者更常见的是使用ToString() 方法进行比较。我们还应该在检查中添加空条件运算符,以防Tag 为空,以避免NullReferenceException

if (c.Tag?.ToString() == btn.Tag?.ToString())

您可能会考虑做的另一件事是创建一个单独的方法来删除具有特定标记的所有控件,以及另一个递归查找具有该标记的所有控件的方法。如果您有一些带有“删除”标签的控件是不同容器的子级,这将有所帮助。

例如:

// 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);
}

【讨论】:

  • "if (control.Tag.ToString() == tag)" 给了我一个 System.NullReferenceException。当我尝试比较“if (c.Tag.ToString() == btn.Tag.ToString()) 时,我遇到了同样的异常。也许问题隐藏在这里?为什么会发生这种情况?
  • 糟糕,忘记添加空条件运算符...现在更新。您的某些标签似乎为空,我们没有先检查。
  • 这是一个非常棒的答案,我非常感谢您为我写下的内容。我很惊讶我在这么短的时间内得到了如此丰富的答案。最后,只需将我的“if (c.Tag == btn.Tag)”更改为“if (c.Tag?.ToString() == btn.Tag?.ToString())”即可解决问题,一切正常像一个魅力。但我肯定会尝试理解您建议的所有其他代码。非常感谢!我保证我也会帮助新人。一旦我开始了解更多,当然:)
猜你喜欢
  • 2017-11-07
  • 2021-11-12
  • 1970-01-01
  • 1970-01-01
  • 2021-10-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-28
相关资源
最近更新 更多