title: Programmatically adding controls to TableLayoutPanel behaves differently based on originating thread
body: <p>I am creating a WinForm project that displays messages from a server and a client.  Client messages are added via standard UI events like Click and KeyPress.  Server messages are added via a background thread that is listening for messages and "alerts" the UI when they arrive.  The "alert" happens through an EventHandler that then makes use of the Invoke method since we are requesting to modify the UI from a thread that did not create it.</p>
  
  <p>When messages are added from the client they appear as desired (i.e. correctly sized, wrapping and resizing performs correctly).  When messages are added from the background thread via Invoke only the first message displays correctly and even then only initially.  Once the form is resized the wrapping stops working and the first message is clipped based on how much space is available.  Messages after the first get sized completely incorrectly in that it appears that their height gets set to 1 pixel or something very small so that only the tops of the characters from the first line can be seen.  Since I am new to WinForms I am suspicious that I am doing something wrong as far as the correct way to programmatically add controls to the UI.</p>
  
  <p>Both the client and the background thread call the same method to add the controls to the form; only the background calls it via Invoke.  I am at a loss as to why the added controls behave differently based on the event they originated from because either way they are being added the exact same way.  My only thought is that I am missing something obvious because I am new to WinForms.</p>
  
  <p>Anyway, enough of the explanation, here is the relevant code:</p>
  
  <pre><code>private void AddMessage(string message)
  {
      tableLayoutPanel1.SuspendLayout();
  
      RichTextBox rtb = new RichTextBox();
      rtb.AppendText(message);
      rtb.Multiline = true;
      rtb.WordWrap = true;
      rtb.Dock = DockStyle.Top;
  
      rtb.ReadOnly = true;
      rtb.BorderStyle = BorderStyle.None;
      rtb.ScrollBars = RichTextBoxScrollBars.None;
      rtb.BackColor = Color.LightBlue;
      rtb.Font = new Font("Tahoma", 8, FontStyle.Italic);
      rtb.Resize += rtb_Resize;
      rtb.MinimumSize = new Size(150, 15);
      rtb.Margin = new Padding(1, 0, 0, 5);
      rtb.Padding = new Padding(3, 3, 3, 3);
      rtb.Height = rtb.GetPositionFromCharIndex(rtb.Text.Length).Y;
  
      tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.AutoSize));
      tableLayoutPanel1.RowCount = tableLayoutPanel1.RowStyles.Count;
      tableLayoutPanel1.Controls.Add(rtb);
      tableLayoutPanel1.SetColumnSpan(rtb, 2);
  
      tableLayoutPanel1.ResumeLayout(true);
      tableLayoutPanel1.AutoScrollPosition = new Point(0, tableLayoutPanel1.VerticalScroll.Maximum);
  }
  
  private void richTextBox1_KeyPress(object sender, KeyPressEventArgs e)
  {
      if (e.KeyChar == 13 &amp;&amp; !String.IsNullOrEmpty(richTextBox1.Text))
      {
          AddMessage(richTextBox1.Text);
          richTextBox1.Clear();
      }
  }
  
  public void PostMessage(object sender, MessageEventArgs e)
  {
      BeginInvoke(new AddMsg(AddMessage), new object[] { e.Message });
  }
  
  public delegate void AddMsg(string m);
  
  private void rtb_Resize(object sender, EventArgs e)
  {
      var rtb = (RichTextBox) sender;
      rtb.Height = rtb.GetPositionFromCharIndex(rtb.Text.Length).Y;
  }
  </code></pre>
  
  <p>Ok, now some more explanation.  Client messages originate from richTextBox1_KeyPress and server messages originate from PostMessage (PostMessage is assigned to the EventHandler for the background thread when it gets a message).  Both as you can see call AddMessage which adds a RichTextBox with the message to the TableLayoutPanel.  The rtb_Resize method contains logic for a way I found online to get a RickTextBox to auto size since apparently it does not support this; maybe this a possible source to my problem.</p>
  
  <p>I'll also provide the designer code below for the TableLayoutPanel since this seems to be helpful and relevant from other posts I've seen on here.</p>
  
  <pre><code>// 
  // tableLayoutPanel1
  // 
  this.tableLayoutPanel1.AutoScroll = true;
  this.tableLayoutPanel1.AutoSize = true;
  this.tableLayoutPanel1.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
  this.tableLayoutPanel1.BackColor = System.Drawing.Color.White;
  this.tableLayoutPanel1.ColumnCount = 2;
  this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
  this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 50F));
  this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;
  this.tableLayoutPanel1.Location = new System.Drawing.Point(1, 10);
  this.tableLayoutPanel1.Name = "tableLayoutPanel1";
  this.tableLayoutPanel1.Padding = new System.Windows.Forms.Padding(5, 5, 12, 5);
  this.tableLayoutPanel1.RowCount = 1;
  this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
  this.tableLayoutPanel1.Size = new System.Drawing.Size(272, 276);
  this.tableLayoutPanel1.TabIndex = 0;
  </code></pre>
  
  <p>The TableLayoutPanel does contain an initial row since the designer does not allow you to have one with no rows, but I clear all the rows out in the Form's constructor after the standard call to InitializeComponent.</p>
  
  <p>Hopefully I've provided enough here to give people the information they need but please let me know if you have any questions or need to see other parts of the code and I will provide them as quickly as possible.  Also, if it matters I'm using Visual Studio 2008 and .NET 3.5.</p>
  
  <p>Thank you.</p>