Visual Studio offers you ways to design forms visually thanks to its Designer. You can simply drag and drop controls, drag them to specified locations, change their properties, and attach events. But how can you add controls during runtime where the tools from Visual Studio are not accessible? You can do so by adding them programmatically. Whenever you place a control to the form, Visual Studio generates a code that creates the object representing the control, initialize the properties specified and attach event handlers specified in the Properties Window. You can see all the generated code using the generated Designer file of every form class you create as discussed in the Separating Design and Functionality lesson.

This time, you will do the same technique that Visual Studio do to create controls. You will be adding a control dynamically during runtime. To demonstrate how we can do this, let’s create an application that adds all the numbers typed by the user. The program will dynamically add labels and text boxes that will hold the numeric input. The number of inputs will be given by the user.

Create a new Windows Forms Application. Add a label, text box and a button as seen below. Change the name of the textbox to textBoxInput, and the button to buttonGenerate.

Dynamic Controls

Dynamic Controls

Go to Code Editor by pressing F7. Use the highlighted code below and put it inside the Form’s constructor right below the InitializeComponent method.

public Form1()
{
    InitializeComponent();
    this.AutoSizeMode = AutoSizeMode.GrowAndShrink;
    this.AutoSize = true;
    this.Padding = new Padding(0, 0, 20, 20);
    this.StartPosition = FormStartPosition.CenterScreen;
}

What we have done here is to demonstrate how we can manually specify values for the properties of a control, in this case, the form. The this keyword specifies the form because the code is inside the Form class. You can now see that these properties (which is normally set using Properties Window) can also be done in code. The first line of code specifies the AutoSizeMode property of the form to grow and shrink whenever necessary to accommodate the controls that will be dynamically added. We then set the AutoSize property to true. We have done this so that the form will automatically resize when new controls are added or removed. We also added padding to the right and bottom of the form as specified by the third line. This is to add some space to the right and bottom of the form since auto size is activated. The StartPosition property of the form allows the form to initially show up in the center of the screen of your monitor.

Before we continue, add a private member for our form class that will accept a collection of TextBoxes.

private List<TextBox> inputTextBoxes;

This will hold all of our input boxes so we can reference each of them and get their individual values for addition.

Go to the Designer by pressing Shift + F7. Double click buttonGenerate to create an event handler for its Click event. Use the following code for the event handler.

private void buttonGenerate_Click(object sender, EventArgs e)
{
    //Get the number of input text boxes to generate
    int inputNumber = Int32.Parse(textBoxInput.Text);

    //Initialize list of input text boxes
    inputTextBoxes = new List<TextBox>();

    //Generate labels and text boxes
    for (int i = 1; i <= inputNumber; i++)
    {
        //Create a new label and text box
        Label labelInput = new Label();
        TextBox textBoxNewInput = new TextBox();

        //Initialize label's property
        labelInput.Text = "Input " + i;
        labelInput.Location = new Point(30, textBoxInput.Bottom + (i * 30));
        labelInput.AutoSize = true;

        //Initialize textBoxes Property
        textBoxNewInput.Location = new Point(labelInput.Width , labelInput.Top - 3);

        //Add the newly created text box to the list of input text boxes
        inputTextBoxes.Add(textBoxNewInput);

        //Add the labels and text box to the form
        this.Controls.Add(labelInput);
        this.Controls.Add(textBoxNewInput);
    }

    //Create an Add button
    Button buttonAdd = new Button();
    //Initialize Properties
    buttonAdd.Text = "Add";
    //Make the button show up in the middle of the form and right below the last input box
    buttonAdd.Location = new Point(this.Width / 2 - buttonAdd.Width / 2,
        inputTextBoxes[inputTextBoxes.Count - 1].Bottom + 20);
    //Add an event handler to the button's click event
    buttonAdd.Click += new EventHandler(buttonAdd_Click);

    //Add the button to the form
    this.Controls.Add(buttonAdd);

    //Center the form to the screen
    this.CenterToScreen();
}

Don’t worry if Visual Studio highlights an error in this code as it will be fixed later. The first thing we did is retrieve the value which indicates how many input boxes and labels to generate. We then initialize the inputTextBoxes variable to prepare it to hold the input boxes. We now enter a for loop which will repeat on generating new labels and text boxes depending on the number specified by the user. Inside the for loop, we created a new Label and TextBox instances. The following codes initializes/modifies the properties of the created controls.

labelInput.Text = "Input " + i;
labelInput.Location = new Point(30, textBoxInput.Bottom + (i * 30));
labelInput.AutoSize = true;

The first line assigns the new label with a text depending on the position of the index in the loop. The second line relocates the position of the new label. If we failed to do this, the label will show up in its default location which is the top left portion of its container. If you are coding the Location and not using the Designer, you might find it hard to estimate the exact location you want your label to show. The Location property accepts a Point value so we created a new Point object using a constructor that accepts the X coordinate and the Y coordinate of the control. The first argument which is the X coordinate was just an estimate location. The Y coordinate uses some simple math so that each control will be added will have a distance relative to the bottom of the top text box (the text box that was used to determine the number of inputs). The expression simply says that the first generated text box will be 30 pixels from the bottom of textBoxInput, the next generated text box will be 60 pixels, the third will be 90 pixels and so on. The AutoSize property is then set to true because the default is false. As you can see, we did not set all the available properties of the Label control because each property has a default value so we can only concentrate on properties that we really want to change. Let’s proceed to the next code which determines the location of the generated input text box.

textBoxNewInput.Location = new Point(labelInput.Width , labelInput.Top - 3);

The Location property of the new text box was assigned with a Point object with an X coordinate equal to the width of its label pair. This makes the text box position right next to the label. The Y coordinate is the same with its label pair, but we subtract 3 pixels so the center of the text box is aligned to the center of its label pair.

inputTextBoxes.Add(textBoxNewInput);

The above code adds the newly created textbox to the TextBox collection that will be used later on. The following method shows how we can add the created controls to the form.

this.Controls.Add(labelInput);
this.Controls.Add(textBoxNewInput);

Controls which serves as containers such as forms has a Controls property which contains all the controls that are inside it. We use its Add method and pass the individual controls to be added. Once they are added to the form, they will now be drawn to the screen once the form is initialized and is finished loading.

this.CenterToScreen();

This code recenters the form in the screen. Since the form’s size was changed when we added controls, this code is necessary.

After all the input boxes are generated, we need to add the button that will add the values that the user will provide.

Button buttonAdd = new Button();;
buttonAdd.Text = "Add";
buttonAdd.Location = new Point(this.Width / 2 - buttonAdd.Width / 2,
    inputTextBoxes[inputTextBoxes.Count - 1].Bottom + 20);
buttonAdd.Click += new EventHandler(buttonAdd_Click);
this.Controls.Add(buttonAdd);

The first line creates the button. Then we specified the text of the button. The third line positions the button to the center of the form and right below the last added input text box. The expression for computing the X coordinate gets the location of the center of the form. Since the left side of the control is positioned to the center, we need to subtract half the width of the button to the calculated center to position it in the middle of the form’s center. We got the Y coordinate by getting the bottom of the last input text box in the inputTextBoxescollection. The last input text box was determined by the index equal to the count of items in the collection subtracted by one.

The next line adds an event handler to its click event. If you didn’t copy the code and type this, right after type +=, Visual Studio will allow you to press Tab twice to automatically generate an event handler for this event. The event handler for this event will be shown later. Right now, we can see that the event handlers name is buttonAdd_Click. The last code simply adds the button to the form.

Type this method which is the event handler for the Click event of the buttonAdd. If this was automatically generated by Visual Studio described by the technique above, then you will find a NotImplementedException inside it which you can simply delete and replace with the following code.

void buttonAdd_Click(object sender, EventArgs e)
{
    int sum = 0;

    foreach (TextBox inputBox in inputTextBoxes)
    {
        if (inputBox.Text == String.Empty)
        {
            MessageBox.Show("Plaese fill in all the text boxes.", "Error",
                MessageBoxButtons.OK, MessageBoxIcon.Error);
            return;
        }
        else
        {
            sum += Int32.Parse(inputBox.Text);
        }
    }
    MessageBox.Show("The Sum is " + sum);
}

This is the code that executes when the button for adding is clicked. You have seen how this code was added as an event handler of the buttonAdd‘s click event. We created a variable that will hold the sum of all the values in each text box. Using a foreach loop, we retrieve each text box and access its content. There is a simple validation inside the loop which test if the text box is filled with a value or is empty. If it is empty, an error is shown and the method is terminated. If there is a valid number inside the text box, it is added to the value of the sum. After looping through all the textboxes and adding each of their values to the sum, the result is then displayed.

Run the program and type 5 in the text box. Click generate and the program will create 5 text boxes.

Dynamic Controls

Dynamic Controls

Watch as the the form is recentered in the screen. Type some values in the text boxes and click the add button to show the sum.

You have now experienced the tedious process of manually creating controls without the help of the Designing tools of Visual Studio. This is not recommended when designing the initial layout of the form. You can use this technique when you wan to dynamically create controls depending on factors that changes such as an input from the user.

Written by compitionpoint

Leave a Comment

Your email address will not be published. Required fields are marked *