Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Align dynamically added controls horizontally and vertically within a control in c# winforms

I have this program that dynamically adds pictureboxes referring to the number of president in the database. How do i put them inside the groupbox and align the pictureboxes inside the groupbox? And the groupbox should stretch if the pictureboxes are many.

I have this codes now :

    private void Form1_Load(object sender, EventArgs e)
    {
        conn.Open();

        try
        {
            cmd = new SqlCommand("SELECT COUNT(Position) FROM TableVote WHERE Position='" + "President" + "'", conn);
            Int32 PresCount = (Int32)cmd.ExecuteScalar();

            TxtPresCount.Text = PresCount.ToString();

            for (int i = 0; i < PresCount; ++i)
            {
                GroupBox PresGB = new GroupBox();
                {
                    PresGB.Size = new Size(491, 152);
                    PresGB.Location = new Point(12, 12);
                    PresGB.Text = "President";
                    this.Controls.Add(PresGB);
                    PresGB.SendToBack();

                    PictureBox PresPB = new PictureBox();
                    PresPB.Location = new Point(80 + (150 * i) + 20, 50);
                    PresPB.Size = new Size(75, 75);
                    PresPB.BorderStyle = BorderStyle.Fixed3D;
                    PresPB.ImageLocation = "imgPath";
                    this.Controls.Add(PresPB);
                    PresPB.BringToFront();
                };
            }
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }
        finally
        {
            conn.Close();
        }
    }

I would want the pictureboxes to be inside the groupbox and align it inside.

like image 310
Lyndon Broz Tonelete Avatar asked Oct 05 '13 00:10

Lyndon Broz Tonelete


1 Answers

Maybe the FlowLayoutPanel control already does what you are trying to do. Just create your picture boxes and add them to a FlowLayoutPanel instead of a GroupBox.

FlowLayoutPanel automatically arranges controls in rows and/or columns depending on the value of its FlowDirection property. Set myFlowLayoutPanel.FlowDirection = FlowDirection.TopDown to get a vertical arranged list.

If you don't want multiple rows or columns set the WrapContents property to false. You can also set the AutoScroll property to true to automatically get scrollbars if the controls don't fit.

If you prefer to have the border of a GroupBox you can still put the FlowLayoutPanel into a GroupBox.

To adjust the space between the picture boxes you can use the Margin property.

This gives you a lot of control over the layout and you don't need to calculate the control positions. Also, if the size of the FlowLayoutPanel changes everything is rearranged automatically.

UPDATE:

I have a few comments on your code:

  1. The curly braces make this look like the syntax of an object initializer - but it isn't.

    GroupBox PresGB = new GroupBox(); // this line ends with a semicolon
    {
        // therefore this is just a block of code not related to new GroupBox()
    };
    

    You should remove the curly braces.

  2. The creation of the group box is inside the loop. I doubt that you want a new group box for each picture box. This is the reason why you only see a single picture. Each new group box hides all the previous ones.

  3. You add the picture boxes to the form instead of the group box.

  4. You use "cryptic" names. PresGB and PresPB are very likely to be swapped accidentally. Abbreviations are usually a bad choice for names.

  5. You don't need to call SendToBack or BringToFront since you don't want the controls to overlap anyway.

  6. I don't think GroupBox is a good choice. Of course you can make it bigger if the number of pictures increases but you are limited by the screen and you don't get scollbars if the picture boxes don't fit. Use a FlowLayoutPanel. It has all the "magic" that you are looking for.

Replace your for loop with this piece of code:

var panel = new FlowLayoutPanel();
panel.SuspendLayout(); // don't calculate the layout before all picture boxes are added
panel.Size = new Size(491, 152);
panel.Location = new Point(12, 12);
panel.BorderStyle = BorderStyle.Fixed3D;
panel.FlowDirection = FlowDirection.LeftToRight;
panel.AutoScroll = true; // automatically add scrollbars if needed
panel.WrapContents = false; // all picture boxes in a single row
this.Controls.Add(panel);

for (int i = 0; i < PresCount; ++i)
{
    var pictureBox = new PictureBox();
    // the location is calculated by the FlowLayoutPanel
    pictureBox.Size = new Size(75, 75);
    pictureBox.BorderStyle = BorderStyle.FixedSingle;
    pictureBox.ImageLocation = "imgPath";
    panel.Controls.Add(pictureBox);
}

panel.ResumeLayout(); 
like image 119
pescolino Avatar answered Oct 13 '22 22:10

pescolino