Search code examples
c#winformsuser-controlstablelayoutpanel

Changing color of TableLayoutPanel when adding manually


I have 2 classes: a form and a user control.

  • I have a default flowlayout in my form and a button to add usercontrol to flowlayout
  • 3 rowed tablelayout in my user control;

When the usercontrol initiliazed, I apply a certain color formatting.

This color formatting works fine when I create instances onLoad. But when I add it per button, color formatting won't apply.

Expected: blue bg color and white label color

EDIT: Found out where the exact problem lays. To be more precised; when I click create new instance, tableLayoutPanel1_CellPaint method won't get triggered.

What am I missing here?

Thank you in advance

Form1

 public partial class Form1 : Form
    {
        List<UserControl1> listUserControl = new List<UserControl1>();

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            listUserControl.Add(new UserControl1(1, "John", 30));
            listUserControl.Add(new UserControl1(2, "Chris", 26));
            listUserControl.Add(new UserControl1(3, "Alice", 45));

            flowLayoutPanel1.Controls.Add(new UserControl1()); // Header column

            foreach (UserControl1 userControl1 in listUserControl)
            {
                flowLayoutPanel1.Controls.Add(userControl1);
            }
        }

        private void buttonAdd_Click(object sender, EventArgs e)
        {
            flowLayoutPanel1.Controls.Add(new UserControl1()); // Add an extra row
        }
    }

Form 1 Designer

  partial class Form1
    {
        /// <summary>
        /// Required designer variable.
        /// </summary>
        private System.ComponentModel.IContainer components = null;

        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #region Windows Form Designer generated code

        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            this.flowLayoutPanel1 = new System.Windows.Forms.FlowLayoutPanel();
            this.buttonAdd = new System.Windows.Forms.Button();
            this.SuspendLayout();
            // 
            // flowLayoutPanel1
            // 
            this.flowLayoutPanel1.Location = new System.Drawing.Point(12, 12);
            this.flowLayoutPanel1.Name = "flowLayoutPanel1";
            this.flowLayoutPanel1.Size = new System.Drawing.Size(327, 99);
            this.flowLayoutPanel1.TabIndex = 0;
            // 
            // buttonAdd
            // 
            this.buttonAdd.Location = new System.Drawing.Point(345, 12);
            this.buttonAdd.Name = "buttonAdd";
            this.buttonAdd.Size = new System.Drawing.Size(82, 99);
            this.buttonAdd.TabIndex = 1;
            this.buttonAdd.Text = "ADD";
            this.buttonAdd.UseVisualStyleBackColor = true;
            this.buttonAdd.Click += new System.EventHandler(this.buttonAdd_Click);
            // 
            // Form1
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(437, 123);
            this.Controls.Add(this.buttonAdd);
            this.Controls.Add(this.flowLayoutPanel1);
            this.Name = "Form1";
            this.Text = "Form1";
            this.Load += new System.EventHandler(this.Form1_Load);
            this.ResumeLayout(false);

        }

        #endregion

        private System.Windows.Forms.FlowLayoutPanel flowLayoutPanel1;
        private System.Windows.Forms.Button buttonAdd;
    }

UserControl1 class

  public partial class UserControl1 : UserControl
    {
        Color colorDarkBlue, colorCream, colorLightGray;
        SolidBrush brushDarkBlue, brushCream, brushLightGray;

        private int id, age;
        private string name;

        private bool _isHeader = false;

        public UserControl1()
        {
            InitializeColors();
            InitializeComponent();
            _isHeader = true;
            ColorLabels(Color.White);
        }

        public UserControl1(int id, string name, int age)
        {
            this.id = id;
            this.name = name;
            this.age = age;

            InitializeColors();
            InitializeComponent();
            ColorLabels(Color.FromArgb(103, 103, 103));
            LoadLabels();
        }

        private void LoadLabels()
        {
            labelID.Text = id.ToString();
            labelName.Text = name;
            labelAge.Text = age.ToString();
        }

        private void InitializeColors()
        {
            colorDarkBlue = Color.FromArgb(60, 71, 133);
            brushDarkBlue = new SolidBrush(colorDarkBlue);

            colorCream = Color.FromArgb(251, 251, 251);
            brushCream = new SolidBrush(colorCream);

            colorLightGray = Color.FromArgb(242, 242, 242);
            brushLightGray = new SolidBrush(colorLightGray);
        }

        private void ColorLabels(Color color)
        {
            labelID.ForeColor = color;
            labelName.ForeColor = color;
            labelAge.ForeColor = color;
        }

        private void tableLayoutPanel1_CellPaint(object sender, TableLayoutCellPaintEventArgs e)
        {
            Graphics g = e.Graphics;
            Rectangle r = e.CellBounds;

            if (_isHeader) /// Set as left header
            {
                g.FillRectangle(brushDarkBlue, r);
            }
            else
            {
                if (e.Row % 2 == 0)
                {
                    g.FillRectangle(brushCream, r);
                }
                else
                {
                    g.FillRectangle(brushLightGray, r);
                }
            }
        }
    }

UserControl1 designer

 partial class UserControl1
    {
        /// <summary> 
        /// Required designer variable.
        /// </summary>
        private System.ComponentModel.IContainer components = null;

        /// <summary> 
        /// Clean up any resources being used.
        /// </summary>
        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #region Component Designer generated code

        /// <summary> 
        /// Required method for Designer support - do not modify 
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
            this.labelID = new System.Windows.Forms.Label();
            this.labelName = new System.Windows.Forms.Label();
            this.labelAge = new System.Windows.Forms.Label();
            this.tableLayoutPanel1.SuspendLayout();
            this.SuspendLayout();
            // 
            // tableLayoutPanel1
            // 
            this.tableLayoutPanel1.CellBorderStyle = System.Windows.Forms.TableLayoutPanelCellBorderStyle.Single;
            this.tableLayoutPanel1.ColumnCount = 1;
            this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
            this.tableLayoutPanel1.Controls.Add(this.labelID, 0, 0);
            this.tableLayoutPanel1.Controls.Add(this.labelName, 0, 1);
            this.tableLayoutPanel1.Controls.Add(this.labelAge, 0, 2);
            this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;
            this.tableLayoutPanel1.Font = new System.Drawing.Font("Calibri", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(162)));
            this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0);
            this.tableLayoutPanel1.Margin = new System.Windows.Forms.Padding(0);
            this.tableLayoutPanel1.Name = "tableLayoutPanel1";
            this.tableLayoutPanel1.RowCount = 3;
            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 15F));
            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 15F));
            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 15F));
            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F));
            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F));
            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F));
            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F));
            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F));
            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F));
            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F));
            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F));
            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F));
            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F));
            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F));
            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F));
            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F));
            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F));
            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F));
            this.tableLayoutPanel1.Size = new System.Drawing.Size(50, 65);
            this.tableLayoutPanel1.TabIndex = 0;
            this.tableLayoutPanel1.CellPaint += new System.Windows.Forms.TableLayoutCellPaintEventHandler(this.tableLayoutPanel1_CellPaint);
            // 
            // labelID
            // 
            this.labelID.AutoEllipsis = true;
            this.labelID.BackColor = System.Drawing.Color.Transparent;
            this.labelID.Dock = System.Windows.Forms.DockStyle.Fill;
            this.labelID.Font = new System.Drawing.Font("Calibri", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(162)));
            this.labelID.Location = new System.Drawing.Point(4, 1);
            this.labelID.Margin = new System.Windows.Forms.Padding(3, 0, 0, 0);
            this.labelID.Name = "labelID";
            this.labelID.Size = new System.Drawing.Size(45, 15);
            this.labelID.TabIndex = 0;
            this.labelID.Text = "ID";
            this.labelID.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
            this.labelID.UseCompatibleTextRendering = true;
            // 
            // labelName
            // 
            this.labelName.AutoEllipsis = true;
            this.labelName.BackColor = System.Drawing.Color.Transparent;
            this.labelName.Dock = System.Windows.Forms.DockStyle.Fill;
            this.labelName.Font = new System.Drawing.Font("Calibri", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(162)));
            this.labelName.Location = new System.Drawing.Point(4, 17);
            this.labelName.Margin = new System.Windows.Forms.Padding(3, 0, 0, 0);
            this.labelName.Name = "labelName";
            this.labelName.Size = new System.Drawing.Size(45, 15);
            this.labelName.TabIndex = 4;
            this.labelName.Text = "Name";
            this.labelName.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
            this.labelName.UseCompatibleTextRendering = true;
            // 
            // labelAge
            // 
            this.labelAge.AutoEllipsis = true;
            this.labelAge.BackColor = System.Drawing.Color.Transparent;
            this.labelAge.Dock = System.Windows.Forms.DockStyle.Fill;
            this.labelAge.Font = new System.Drawing.Font("Calibri", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(162)));
            this.labelAge.Location = new System.Drawing.Point(4, 33);
            this.labelAge.Margin = new System.Windows.Forms.Padding(3, 0, 0, 0);
            this.labelAge.Name = "labelAge";
            this.labelAge.Size = new System.Drawing.Size(45, 31);
            this.labelAge.TabIndex = 5;
            this.labelAge.Text = "Age";
            this.labelAge.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
            this.labelAge.UseCompatibleTextRendering = true;
            // 
            // UserControl1
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.BackColor = System.Drawing.Color.White;
            this.Controls.Add(this.tableLayoutPanel1);
            this.Margin = new System.Windows.Forms.Padding(0);
            this.MaximumSize = new System.Drawing.Size(50, 285);
            this.Name = "UserControl1";
            this.Size = new System.Drawing.Size(50, 65);
            this.tableLayoutPanel1.ResumeLayout(false);
            this.ResumeLayout(false);

        }

        #endregion

        public System.Windows.Forms.TableLayoutPanel tableLayoutPanel1;
        public System.Windows.Forms.Label labelID;
        public System.Windows.Forms.Label labelAge;
        public System.Windows.Forms.Label labelName;
    }

Solution

  • After struggling of hours, I've found it.

    what @Jimi mentioned in the comments, I've already tried them all already. Update(), Invalidate() nor Refresh() worked. The trick was; after adding the control manually, i must call SuspendLayout() and ResumeLayout(true) on my tablelayout. So;

    private void buttonAdd_Click(object sender, EventArgs e)
    {
        UserControl1 userControl = new UserControl1();
        userControl.tableLayoutPanel1.SuspendLayout();        
        flowLayoutPanel1.Controls.Add(userControl);
        userControl.tableLayoutPanel1.ResumeLayout(true);
    }
    

    This is from Microsoft's official documentation. LINK

    The layout logic of the control is suspended until the ResumeLayout method is called.

    The SuspendLayout and ResumeLayout methods are used in tandem to suppress multiple Layout events while you adjust multiple attributes of the control. For example, you would typically call the SuspendLayout method, then set the Size, Location, Anchor, or Dock properties of the control, and then call the ResumeLayout method to enable the changes to take effect.

    There must be no pending calls to SuspendLayout for ResumeLayout to be successfully called.