Flag This Hub

Creating C# controls on the fly

By


Dynamic control creation

This article applies to dynamically creating controls in C# in the Windows environment (WinForms). Many people who are starting out programming are quite comfortable with the idea of dragging and dropping controls onto a form in the Integrated Development Environment (IDE) but find it less intuitive when they are first faced with the requirement of creating a control as and when required at run-time.

For the purpose of this article the reader is assumed to be comfortable with creating controls on a form using the IDE, but to have no previous experience of creating a control dynamically. It it also assumed that you have a basic grasp of adding data members to forms which is to say you understand the following:

// reference accessing the C# windows controls
using System.Windows.Form;

// Definition of the form class
public partial class Form1 : Form
{
    // The data member that is going to hold our dynamically created control
    private TextBox Text1 = null;

    // Constructor
    public MainForm()
    {
    }
}

To follow the instructions in this explanation you will need to have created a form with a command button on it as a starting point. We assume here that it is called Button1 but you can interpret the code accordingly.

The first thing you will need to do is add a data member for the control that you wish to create. You will use this to refer to the control in your code throughout it's lifecycle. For our example we will create a text box dynamically, so make sure your form declares it as follows:

    private TextBox Text1 = null;

You can see from the code above where this line should be in relation to the code generated automatically by your IDE for the form. The TextBox control will be exactly the same as one that you would drag and drop from the editor with the important difference that you will create it at run-time only when required.

In the Click event for your button you should add code as follows:

void Button1Click(object sender, EventArgs e)
{
    // make sure we didn't already create the text box
    if (Text1 != null)
    {
        MessageBox.Show("Already made it!");
    }
    else
    {
        // this creates the text box
        Text1 = New TextBox();
        // set up the left and top position (the same as changing the location in the IDE)
        Text1.Left = 100;
        Text1.Top = 100;
        // put an initial value for the text in the box
        Text1.Text = "Hello, I'm new to this form";
        // add the newly created control to the form
        this.Controls.Add(Text1);
    }
}

It's that simple - when you click the button for the first time, it will create a text box that will appear on your form that was not there at design time. It won't be there at design time when you go back to the design time environment either.

To do the same things you would have controlled through the IDE you will find that the object created in code (here a TextBox but you could create any other control as well) will have the same properties you can access in the IDE. One reason we are declaring the TextBox as a data member on the form is to simplify access to it after creation, it is technically possible not to declare it. At the most brief, a single line of code could actually have done it:

this.Controls.Add(new TextBox);

This however would make it quite hard to access the newly created TextBox since we would need to iterate through the Controls collection of the form.

Incidentally until you use the Add method of the Controls collection of the form (accessed here using the "this" keyword), the control will not appear on the form. You can create controls and keep them to one side and just add or remove them as required in this way.

Later, you might want to add event handlers to the controls you have created dynamically, this can also be done in code. To do this the following will work.

Add this code to your form:

void Text1TextChanged(object sender, EventArgs e)
{
    MessageBox.Show("Text changed!");
}

Then change the earlier code as follows:

// this creates the text box
Text1 = New TextBox();
Text1.TextChanged += new EventHandler(TextBox1TextChanged);

This will dynamically link the text changed event of the newly created text box to the code that already existed to handle it. There is nothing stopping you from using exactly the same code to handle events from multiple text boxes or even other controls (where the event has the same parameter signature). So if you created a second text box or even a button they could use the same code to handle the event. Sometimes this can be useful to promote code reuse.

There is one very important thing to keep in mind as you start to use this technique to a more advanced level. The controls within the controls collection of the form will automatically be destroyed when the form is destroyed. If you remove them from the collection they will be tidied up by the C# garbage collector when there are no more references to them. If you have references to a control you have created elsewhere in your code however (for example if another form refers to the created control) you will get exceptions if attempting to reference the control after destroying the form that contains it (in the Controls collection).

If you want to keep using the dynamically created control you need to Remove it from the Controls collection before destroying the owner of that Controls collection (the form in this example). There is nothing to stop you from adding it into the Controls collection of another form however.

I regularly create complex user interfaces on the fly in scenarios where I have repeating elements but I do not know how many, so I hope this is a useful introduction to the subject.

It is not complicated, but I think people often struggle initially with the idea that their code is doing the same things the IDE is behind the scenes (and if you look at the automatically generated code, you will see it is doing it exactly the same way behind the scenes).

Comments

Gary Bouchard 5 months ago

Great article that clarified a couple of things for me, however, can you expound on creating the dynamic controls on say a TAB Control and then accessing those dynamically created controls from an outside class?

Submit a Comment
Members and Guests

Sign in or sign up and post using a hubpages account.



    Like this Hub?
    Please wait working