Building Dynamic .NET Controls with Windows Forms
 
Published: 07 Sep 2007
Abstract
This article demonstrates how to load Controls dynamically, as well as position and align them according to their text length.
by Vishal Patil
Feedback
Average Rating: This article has not yet been rated.
Views (Total / Last 10 Days): 25790/ 48

Introduction

In many projects we encounter the situation where we need to load controls dynamically on the form, as well as position and align them properly. Generally we do this when we are not sure about the number of fields to be displayed and their text size. Imagine a situation where there are several modules and for each module a pop dialog with different field names should be displayed. Instead of creating an individual popup dialog for each module, we can create one popup dialog and based on module name, pass the field names to the pop dialog which will dynamically load, position and align controls on it. This helps take advantage of flexibility and gives us the power of adding controls at runtime.

In the below example I will demonstrate how to achieve this.

The Design

Create a Windows Form application using Visual Studio and add the following code.

Listing 1

public void CreateControls(string[]arrFields)
{
  int YPos = 0;
  int XPos = 0;
  const int HORIZONTALSPACE_FROM_LEFT = 8;
  const int HORIZONTALSPACE_BETWEEN_CTRLS = 16;
  int tabIndex = 0;
  int MaxCtrlWidth = GetMaxControlWidth(arrFields);
  nudControls.Clear();
 
  for (int Count = 0; Count < arrFields.Length; Count++)
  {
    YPos = (nudControls.Count * 25) + 32;
 
    // Field Name Label
    Label lblFieldName = new Label();
    lblFieldName.Location = new System.Drawing.Point(8, YPos);
    lblFieldName.Name = "lbl" + arrFields[Count];
    lblFieldName.Size = new System.Drawing.Size(MaxCtrlWidth, 22);
    lblFieldName.Text = arrFields[Count];
 
    // Set the Horizontol position for NumericUpDown control
    XPos = HORIZONTALSPACE_FROM_LEFT + MaxCtrlWidth +
      HORIZONTALSPACE_BETWEEN_CTRLS;
 
    // Numeric updown
    NumericUpDown nudNum = new NumericUpDown();
    nudNum.Location = new System.Drawing.Point(XPos, YPos);
    nudNum.Name = "txt" + arrFields[Count];
    nudNum.Size = new System.Drawing.Size(48, 22);
    nudNum.TabIndex = ++tabIndex;
 
 
    // Set the Horizontol position for Checkbox control
    XPos = HORIZONTALSPACE_FROM_LEFT + MaxCtrlWidth +
      HORIZONTALSPACE_BETWEEN_CTRLS + 48+HORIZONTALSPACE_BETWEEN_CTRLS;
 
    // checkbox
    CheckBox chk = new CheckBox();
    chk.Location = new System.Drawing.Point(XPos, YPos);
    chk.Name = "chk" + arrFields[Count];
    chk.Size = new System.Drawing.Size(18, 22);
    chk.TabIndex = ++tabIndex;
    chk.TabStop = false;
 
    // Add the new controls to this form
    this.Controls.Add(lblFieldName);
    this.Controls.Add(nudNum);
    this.Controls.Add(chk);
 
    nudControls.Add(arrFields[Count], nudNum);
  }
  // Adjusts the screen size
  SizeToFit(YPos, XPos);
 
}

In the above code, the initial values are set for X, Y positions and for horizontal spaces between controls. All of the label Field Names are set by determining the maximum control width among all the label controls. Then iterating through the array of fields, Label, Numeric updown and checkbox controls are placed on the form by determining the X and Y Positions and the vertical and horizontal spaces between the controls. Once all the controls are placed on the form, the form is resized depending upon the X and Y positions used by the controls.

Listing 2

private int GetMaxControlWidth(string[]Fields)
{
  int mxmFieldWidth = 0;
 
  for (int count = 0; count < Fields.Length; count++)
  {
    // lblName
    Label lblFieldName = new Label();
 
    lblFieldName.AutoSize = true;
    lblFieldName.Text = Fields[count];
 
    Graphics grap = lblFieldName.CreateGraphics();
 
    // Get the Size needed to accommodate the formatted Text.
    Size preferredSize = grap.MeasureString(lblFieldName.Text,
      lblFieldName.Font).ToSize();
 
 
    if (count == 0)
    {
      mxmFieldWidth = preferredSize.Width;
    }
    else
    {
      if (preferredSize.Width > mxmFieldWidth)
      {
        mxmFieldWidth = preferredSize.Width;
 
      }
    }
  }
  return mxmFieldWidth;
}

Aim of the above code is to get the Maximum control width among all the field names' controls (Label control) and set this width to all the label controls. In the above code a label control is drawn. An auto size property is set to true and the Field Name is set to it. Once the Field name is set, control automatically resizes then uses the GDI graphics object to get the size needed to accommodate the formatted text. Then we compare the size of all the label controls and whichever is maximum we set it to all the label controls.

Listing 3

private void SizeToFit(int VertPos, int HoriPos)
{
  Size size = new Size(HoriPos + 25, VertPos + 70);
  this.ClientSize = size;
}

The above code is called after the dynamic controls were created. It receives Parameters VertPos and HoriPos (which are the last vertical and horizontal position of the last item added) and Rrsizes the form, adding some bottom and left spacing.

Testing the application

Add the code given below in the form constructor.

Listing 4

public frmDynamicallyLoadingCtrls()
{
  InitializeComponent();
  string[] str = { "Field 1", "Field 2""Field 3""Maximum Length Field 4",
    "Field 5""Field 6" };
  CreateControls(str);
}

In the above listing we initialize the fields to be displayed on the form. Six fields are defined in the string array and it is passed to CreateControls method to dynamically load the controls.

Now run the form upon and the following screen will be displayed.

Figure 1

Add the field names as below in the form constructor and run the form again.

Listing 5

public frmDynamicallyLoadingCtrls()
{
  InitializeComponent();
  string[] str = { "Field 1", "Field 2""Field 3""Maximum Length Field 4",
  "Field 5""Field 6""Very Very long Maximum Length Field 7""Field 8" };
  CreateControls(str);
}

Figure 2

If you notice in both screens, Field name lengths are resized, positioned and aligned based on maximum length of label field name controls. Others controls are also aligned and positioned accordingly. Similarly, try adding or deleting field names to the string array in Listing 4.

Downloads

References

Conclusion

As you can see, the above sample program can be reused by different modules across applications by loading controls dynamically to provide flexibility to design a common dialog for similar functionality.



User Comments

Title: good   
Name: kumar
Date: 2010-10-14 4:28:46 AM
Comment:
Your concept is good, and give some realtime examples.
Title: ABCD   
Name: EFGH
Date: 2008-05-15 8:48:45 AM
Comment:
Good

Product Spotlight
Product Spotlight 





Community Advice: ASP | SQL | XML | Regular Expressions | Windows


©Copyright 1998-2024 ASPAlliance.com  |  Page Processed at 2024-03-29 11:47:01 AM  AspAlliance Recent Articles RSS Feed
About ASPAlliance | Newsgroups | Advertise | Authors | Email Lists | Feedback | Link To Us | Privacy | Search