【问题标题】:How to programmatically remove Form controls如何以编程方式删除表单控件
【发布时间】:2016-07-23 00:50:28
【问题描述】:

我正在尝试制作一个 winForms 应用程序,其中,numericUpDown 的每次增加最终都应该使面板控件可见,并创建一个文本框控件、一个图片框、一个 numericUpDown 控件和三个标签。而且每次减少,都应该去掉这组控件。我已经设法编写了创建控件的代码,但我不知道如何删除它们。我唯一的猜测是为每个控件分配一个名称,然后使用colorPanel.Controls.RemoveByKey()。不太确定如何处理nameTextBoxPositionYnewLabelPositionY,在他们目前的状态下,他们可能会搞砸一切。还是我应该放弃,使用switch(regionNumber),手动创建控件,然后根据 numericUpDown 值使它们可见?考虑到 numericUpDown 的最大值是 10,这将是一件很麻烦的事。

    private Label newLabel;
    private TextBox nameTextBox;
    private NumericUpDown heightNumericUpDown;
    private PictureBox colorPictureBox;
    private string[] newLabelText = {"Name", "Height", "Color"};

    private int newLabelPositionX = -3;
    private int newLabelPositionY = 5;

    private int nameTextBoxPositionX = 74;
    private int nameTextBoxPositionY = 2;
    private void numberOfRegions_ValueChanged(object sender, EventArgs e)
    {            
        int regionNumber = Convert.ToInt32(numberOfRegions.Value);
        int numberOfLabels = 3;            

        if (regionNumber > 0)
        {
            colorPanel.Visible = true;                                                          
            for (int i = 0; i < regionNumber; i++)
            {
                nameTextBox = new TextBox();                                       
                nameTextBox.Size = new System.Drawing.Size(81, 20);
                nameTextBox.Location = new System.Drawing.Point(nameTextBoxPositionX, nameTextBoxPositionY);
                colorPanel.Controls.Add(nameTextBox);
                nameTextBoxPositionY += 78;                                                    
                for (int a = 0; a < numberOfLabels; a++)
                {
                    newLabel = new Label();
                    newLabel.Location = new System.Drawing.Point(newLabelPositionX, newLabelPositionY);
                    newLabel.Text = newLabelText[a];
                    colorPanel.Controls.Add(newLabel);
                    newLabelPositionY += 26;                        
                }                                     
            }
            newLabelPositionY = 5;
            nameTextBoxPositionY = 2;               
        }
        else
        {
            colorPanel.Visible = false;
        }            
    }

【问题讨论】:

  • 这里的所有答案都有一个非常、非常严重的错误。从其父控件集合中移除的控件必须被释放。不这样做会导致垃圾收集器无法修复的永久内存泄漏。顺便说一句,使用任务管理器轻松诊断,添加 USER Objects 列。您会看到您的流程显示的数字不断增加。您的程序在达到 10,000 时崩溃。
  • 那么应该如何处理这些控件呢?我想,这并不像在for 循环中调用nameTextBox.Dispose() 那样简单。
  • 只需编写一个存储对这 4 个控件的引用的小结构。使用Stack&lt;&gt; 来存储它们。现在很简单。
  • 你需要使用用户控件

标签: c# winforms


【解决方案1】:

您可以简单地遍历您的控件并按名称删除不需要的项目(假设您将它们的名称存储在数组中,甚至标记假设您为每个创建的控件分配一个数字标签(例如 regionNumber)

foreach (Control item in colorPanel.Controls.OfType<Control>())
{
    foreach(var name in myItemNames) 
    {
        if (item.Name == name)
        {
            colorPanel.Controls.Remove(item);
            item.Dispose();
            //...

或者,如果这是您真正想要实现的目标,您可以清除控件

colorPanel.Controls.Clear();

myItemNames 这里将是您在生成控件时分配给的数组。例如

//before loop
myItemNames = new List<string>();

//...in loop
newLabel = new Label();
newLabel.name = "label"+i;
myItemNames.Add(newLabel.name);

【讨论】:

    【解决方案2】:

    使用Control.Controls.Remove方法:

    this.Controls.Remove(Control);
    

    也许将代码更改为使用数组,然后您可以按索引删除控件:

    TextBox[] MyTextBoxes = new TextBox[50];
    
    foreach (TextBox textBox in MyTextBoxes)
        this.Controls.Add(textBox);
    
    foreach (TextBox textBox in MyTextBoxes)
        this.Controls.Remove(textBox);
    

    【讨论】:

      【解决方案3】:

      感谢您的回答,但我已经摆弄Controls.RemoveByKey() 并找到了解决方案:

      struct DynamicFormControls
      {
          public TextBox textBox;
          public Label label;
      }
      
      DynamicFormControls dynamicControls = new DynamicFormControls();
      Stack<Control> controlStack = new Stack<Control>();
      private string[] newLabelText = {"Name", "Height", "Color"};
      private int newLabelPositionX = -3;
      private int newLabelPositionY = 5;
      private int nameTextBoxPositionX = 74;
      private int nameTextBoxPositionY = 2;
      private int numberOfLabels = 3;
      private int currentValue = 0;
      private int previousValue = 0;
      private int difference = 0;
      private int nameSuffix1 = 1;
      private int nameSuffix2 = 1;
      
      private void numberOfRegions_ValueChanged(object sender, EventArgs e)
      {
          currentValue = Convert.ToInt32(numberOfRegions.Value);
          if (currentValue == 0)
          {
              colorPanel.Visible = false;
              colorPanel.Size = new System.Drawing.Size(161, 10);
          }
          if (!ValueIncreased())
          {
              RemoveControls();
          }
          else
          {
              colorPanel.Visible = true;            
              CreateControls();
          }
      }
      
      private bool ValueIncreased()
      {
          if (currentValue > previousValue)
          {
              difference = currentValue - previousValue;
              previousValue = currentValue;
              return true;
          }
          else
          {
              difference = previousValue - currentValue;
              previousValue = currentValue;
              return false;
          }
      }
      
      private void CreateControls()
      {
          for (int i = 0; i < difference; i++)
          {
              dynamicControls.textBox = new TextBox();
              dynamicControls.textBox.Name = "textBox" + nameSuffix1;
              dynamicControls.textBox.Size = new System.Drawing.Size(81, 20);
              dynamicControls.textBox.Location = new System.Drawing.Point(nameTextBoxPositionX, nameTextBoxPositionY);                
              colorPanel.Controls.Add(dynamicControls.textBox);
              controlStack.Push(dynamicControls.textBox);
              nameTextBoxPositionY += 78;
              nameSuffix1++;                
              for (int a = 0; a < numberOfLabels; a++)
              {
                  dynamicControls.label = new Label();
                  dynamicControls.label.Name = "label" + nameSuffix2;
                  dynamicControls.label.Location = new System.Drawing.Point(newLabelPositionX, newLabelPositionY);
                  dynamicControls.label.Text = newLabelText[a];
                  colorPanel.Controls.Add(dynamicControls.label);
                  controlStack.Push(dynamicControls.label);
                  newLabelPositionY += 26;
                  nameSuffix2++;
              }
          }
      }
      
      private void RemoveControls()
      {
          for (int d = 0; d < difference; d++)
          {                
              for (int b = 0; b < 6; b++)
              {
                  controlStack.Pop().Dispose();
              }
              nameSuffix1--;            
              if (nameTextBoxPositionY > 2)
              {
                  nameTextBoxPositionY -= 78;
              }
              for (int t = 0; t < numberOfLabels; t++)
              {
                  nameSuffix2--;
                  if (newLabelPositionY > 5)
                  {
                      newLabelPositionY -= 26;
                  }
              }
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-02-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-08-16
        相关资源
        最近更新 更多