Show controls added programatically in WinForms ap

2019-01-09 19:16发布

问题:

Using Visual Studio (any version will do), is it possible for controls added programatically (rather than via the Design view) to then be shown when switching back to the Design view?

I've tried something ridiculously simple like:

public Form1()
{
    AddCtrl();
    InitializeComponent();
    AddCtrl();
}

private void AddCtrl()
{
    this.SuspendLayout();
    this.Controls.Add(new TextBox());
    this.ResumeLayout(false);
    this.PerformLayout();
}

...but to no avail.

Whilst I'm sure this has been asked before, as it seems a common question, I can't seem to to find an answer!

回答1:

Does the designer run my code?

When a form shows in designer, the designer deserialize the code of your form (Form1.Designer.cs or first class in Form1.cs) and creates an instance of the base class of your form and deserialize InitializeComponent and creates controls that you declared in your class and set their properties.

So the codes in Constructor won't run. The designer only creates an instance of the base class of your form and don't look in constructor of your form.

Interesting example of how the designer works

Look at below code and pay attention to this problems:

  • Where are ;s?
  • Constructor Form111111 for Form1?
  • What is NotDefinedFunction()?
  • How can int i = "xxxxxxxxxx"?

Even if you create such file, the designer will show correctly.

using System
using System.Collections.Generic
using System.Drawing
using System.Windows.Forms
namespace Sample
{
    public class Form1:Form
    {
        public Form111111()
        {
            NotDefinedFunction()
            InitializeComponent()
        }
        public void InitializeComponent()
        {
            int i = "xxxxxxxxxx"
            this.textBox1 = new System.Windows.Forms.TextBox()
            this.SuspendLayout()
            // 
            // textBox1
            // 
            this.textBox1.Location = new System.Drawing.Point(0, 0)
            this.textBox1.Name = "textBox1"
            this.textBox1.Text = "text of text box 1";
            // 
            // Form1
            // 
            this.Controls.Add(this.textBox1)
            this.Name = "Form1"
            this.Text = "Form1"
            this.Size= new Size(250,100)
            this.ResumeLayout(false)
            this.PerformLayout()
        }
        private TextBox textBox1
    }
}

And you will see the form in designer:

How can I add controls dynamically at design time?

If you need such functionality, you can create your dynamic controls in constructor of a base class for your form, since constructor of base class will run when you open a child form in designer, then it will run at design time.

But you should know these controls are inherited and can't be changed using designer of child form.

So simply create a Form2:

public Form2()
{
    InitializeComponent();
    AddDynamicControls();
}

private void AddDynamicControls()
{
    this.Controls.Add(
       new TextBox() { 
          Name = "TextBox1", Text = "Dynamic", Location = new Point(100, 0) });
}

Build the project and then change base class of Form1 to inherit from Form2:

public class Form1:Form2

And the result will be:

Is there any other solution?

If you want to generate some controls really at design time, I think you should take a look at T4 Text Templates.

You can use t4 templates to generate code at design-time. Probably you have seen Entity Framework .tt template files. You can add new Text Template item to your project and put the logic for generating items at design-time in your t4 template.