Dynamically creating labels and textboxes in a panel

  • Thread starter Thread starter Wade
  • Start date Start date
W

Wade

Hi all,

I have an array of polygons, and I need to create controls so that people
can set absolute coordinates (in decimal degrees) for each of the points
within each of the polygons (we also call these polygons sections).

To do this, I have created a method that I call and pass some information to
it so that it can create the appropriate labels and textboxes. While this
has worked successfully, I have found that it can be very slow if I'm
creating, say, two sections each with 10+ points.

Can anyone give me any advice as to a better way to do this? Thanks in
advance!

Here's the method I'm using for creating the controls:

private void CreateCoordinateControls()
{
Point pt = new Point(0, 0);
Label lbl = null;
TextBox txt = null;
Point ptLabel = new Point();
Point ptTextbox = new Point();

int iSectionNum = 1;
int iPointNum;

// loop through each polygon
foreach (DictionaryEntry m_DE in polygons)
{
polygonPointsArray = (ArrayList)m_DE.Value;
polygonPoints = new Point[polygonPointsArray.Count];

iSectionNum += 1;
iPointNum = 1;

// loop through each point
for (int i = 0; i < polygonPointsArray.Count; i++)
{
polygonPoints = (Point)polygonPointsArray;

// create the controls for this point
DefinePointControls(
pt,
"Point",
iPointNum,
iSectionNum,
lbl,
txt,
ptLabel,
ptTextbox);

// increment
iPointNum += 1;
pt.Y += 22;
}
}
}

private void DefinePointControls(
Point pt, // starting point of the controls
string sLabelText, // text to use for the label
int iControlNum, // the current row number
int iSectionNum, // the current section number
Label lbl, // the label control
TextBox txt, // the textbox control
Point ptLabel, // variable used for determining label location
Point ptTextbox // variable used for determining textbox
location
)
{
// set the local variables

ptLabel = pt;
ptTextbox = pt;

// update the label to vertically align it with the middle of
the textbox
ptLabel.Y += 3;

// Create the point label
lbl = new Label();

ptLabel.X += 17;

lbl.Location = ptLabel;
lbl.Name = "lblPoint" + iSectionNum.ToString() + "_" +
iControlNum.ToString();
lbl.Size = new System.Drawing.Size(33, 20);
lbl.Text = sLabelText;

pnlCoordinates.Controls.Add(lbl);

// X-coordinate textbox
txt = new TextBox();

ptTextbox.X += 50;

txt.Location = ptTextbox;
txt.Name = "txtPointX" + iSectionNum.ToString() + "_" +
iControlNum.ToString();
txt.Size = new System.Drawing.Size(74, 20);
txt.Text = "";

pnlCoordinates.Controls.Add(txt);

// X-coordinate label
lbl = new Label();

ptLabel.X += (33 + 74);

lbl.Location = ptLabel;
lbl.TextAlign = ContentAlignment.TopCenter;
lbl.Name = "lblX" + iSectionNum.ToString() + "_" +
iControlNum.ToString();
lbl.Size = new System.Drawing.Size(10, 20);
lbl.Text = "X";

pnlCoordinates.Controls.Add(lbl);

// Y-Coordinate textbox
txt = new TextBox();

ptTextbox.X += 84;

txt.Location = ptTextbox;
txt.Name = "txtPointY" + iSectionNum.ToString() + "_" +
iControlNum.ToString();
txt.Size = new System.Drawing.Size(74, 20);
txt.Text = "";

pnlCoordinates.Controls.Add(txt);

// Y-coordinate label
lbl = new Label();

ptLabel.X += 84;

lbl.Location = ptLabel;
lbl.TextAlign = ContentAlignment.TopCenter;
lbl.Name = "lblY" + iSectionNum.ToString() + "_" +
iControlNum.ToString();
lbl.Size = new System.Drawing.Size(10, 20);
lbl.Text = "Y";

pnlCoordinates.Controls.Add(lbl);
}
 
An article (can't remember the title) suggested to replace

a.Controls.Add(b); by b.Parent = a;

which is told to be more efficient. Further it might be possible to
reuse a number of pre-created controls rather than instanciating new
ones.
 
Thanks, Tamberg.

Sorry for the silly question, but how would I reuse the same control for
multiple instances? Don't I need to re-instantiate it each time?
 
Assuming your UI displays more than one set of data (not simultaneous)
you could reuse multiple instances (from sort of a control-pool) to
display different sets of data.
 
So instead of doing this:

for(int i =0; i<10; i++)
{
Controls.Add(new Label);
}

You can save performance by doing this:

Label l = new Label();
for(int i =0; i<10; i++)
{
Controls.Add(l);
}

You just have to remember to change the positioning.
 
Adding the same instance more than once won't work. But if you display
multiple sets of data (one set after the other, refreshing the screen
for a new set) you could reuse a fixed number of instances.
 
Seems to me that this would just keep moving the same label around the
screen, until it finally finished and I had only one label in the final
position. Right?
 
Hi Tam,

Unfortunately, I don't follow. What do you mean, "refreshing the screen for
a new set"? I would really appreciate a simple example.

I need to be able to create X number of textboxes so that the user can
associate some data to pre-existing points defined in a polygon. If you
have a method that would make the rendering of these controls faster than
what I originally posted, I would be very grateful.

Thanks,

Wade
 
An article (can't remember the title) suggested to replace
a.Controls.Add(b); by b.Parent = a;

Using two calls to set size and location also slows down..
I've created a Label subclass like this:

public class MyLabel : System.Windows.Forms.Label
{
public Label(System.Windows.Forms.Control aParent, int x, int y, int w,
int h) : this ()
{
this.Parent = aParent;
this.Bounds = new Rectangle(x, y, w, h);
}
}

So in you code, just use
lbl = new MyLabel(pnlCoordinates, ptLabel.X, ptLabel.Y, 10, 20)
or something simular..

I gave my application a visible speed boost to create all controls this way.
Your code will also look more clean :)

Cheers,
Lars
 
What's the best way to dispose of dynamic controls such as these?

lbl.Dispose();

Cheers,
Lars
 
Back
Top