views:

954

answers:

4

I have a little demonstration below of a peculiar problem.

using System;
using System.Windows.Forms;

namespace WindowsApplication1
{
    public class TestForm : Form
    {
     private System.Windows.Forms.TabControl tabControl1;
     private System.Windows.Forms.TabPage tabPage1;
     private System.Windows.Forms.TabPage tabPage2;
     private System.Windows.Forms.TextBox textBox1;

     public TestForm()
     {
      //Controls
      this.tabControl1 = new System.Windows.Forms.TabControl();
      this.tabPage1 = new System.Windows.Forms.TabPage();
      this.tabPage2 = new System.Windows.Forms.TabPage();
      this.textBox1 = new System.Windows.Forms.TextBox();

      // tabControl1
      this.tabControl1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
         | System.Windows.Forms.AnchorStyles.Left)
         | System.Windows.Forms.AnchorStyles.Right)));
      this.tabControl1.Controls.Add(this.tabPage1);
      this.tabControl1.Controls.Add(this.tabPage2);
      this.tabControl1.Location = new System.Drawing.Point(12, 12);
      this.tabControl1.Name = "tabControl1";
      this.tabControl1.SelectedIndex = 0;
      this.tabControl1.Size = new System.Drawing.Size(260, 240);
      this.tabControl1.TabIndex = 0;
      this.tabControl1.Selected += new System.Windows.Forms.TabControlEventHandler(this.tabControl1_Selected);

      // tabPage1
      this.tabPage1.Controls.Add(this.textBox1);
      this.tabPage1.Location = new System.Drawing.Point(4, 22);
      this.tabPage1.Name = "tabPage1";
      this.tabPage1.Size = new System.Drawing.Size(252, 214);
      this.tabPage1.TabIndex = 0;
      this.tabPage1.Text = "tabPage1";

      // tabPage2
      this.tabPage2.Location = new System.Drawing.Point(4, 22);
      this.tabPage2.Name = "tabPage2";
      this.tabPage2.Size = new System.Drawing.Size(192, 74);
      this.tabPage2.TabIndex = 1;
      this.tabPage2.Text = "tabPage2";

      // textBox1
      this.textBox1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
         | System.Windows.Forms.AnchorStyles.Right)));
      this.textBox1.Location = new System.Drawing.Point(6, 38);
      this.textBox1.Name = "textBox1";
      this.textBox1.Size = new System.Drawing.Size(240, 20);
      this.textBox1.TabIndex = 0;

      // TestForm
      this.ClientSize = new System.Drawing.Size(284, 264);
      this.Controls.Add(this.tabControl1);
      this.Name = "Form1";
      this.Text = "Form1";
     }

     //Tab Selected
     private void tabControl1_Selected(object sender, EventArgs e)
     {
      this.Text = "TextBox Width: " + this.textBox1.Width.ToString();
     }
    }

    //Main
    static class Program
    {
     static void Main()
     {
      Application.Run(new TestForm());
     }
    }

}

If you run the above C# code you will have a small form containing a tabcontrol. Within the tabcontrol is a texbox on the first tab. If you follow these steps you will see the problem:

  1. Select tabPage2 (textBox1's width is reported in the form title)
  2. Resize the form
  3. Select tabPage1 (The wrong textBox1 width is reported)

Any ideas what is going on here? The textbox is obviously bigger than what is being reported. If you click again on tabPage2 the correct size is then updated. Obviously there is an event updating the width of textBox1. Can i trigger this when tabPage1 is selected?

A: 

Not sure if I understand the problem. But, you might use textbox's resize event to capture the width change OR form's resize.

In your example, does the select event of tabPage1 fire when you do step 3?

shahkalpesh
The select event does fire - but before the tab page is actually made visible, which causes the text box size to be recalculated.
Jon Skeet
+1  A: 

Firstly, thanks for the complete program - it made it much easier to work out what was going on!

While the textbox isn't visible, it isn't resized. When you select tabPage1, the Selected event fires before the controls become visible and the textbox gets laid out again.

Now, that's why it's happening - but what's your real situation? If you actually want to capture the size of controls changing, subscribe to their Resize events. If not, could you explain more about what you're trying to achieve?

Jon Skeet
Jon, I need to learn a lot from you. I didnt think of it in terms of how windows eventing would work.Makes sense. The paint of textbox will occurr only afeter the tabPage selection event completes, I guess.Thanks a lot for your preciseness.
shahkalpesh
No problem. It doesn't help you get round the problem though...If you attach an event handler to tabPage1.VisibleChanged that gets it at the right point, which *might* help you...
Jon Skeet
Thanks, that really helped a lot! I am using a panel control as a container for customs controls that are laid out according to its width. It was not updating due to the width being reported incorrectly. Subscribing to the resize event of the panel cures this. Simple stuff, can't believe i missed it
Gary Willoughby
+1  A: 

I'm pretty sure that what's happening is the Selected event is raised slightly before the tab page becomes visible. The text box is not resized until the tab page becomes visible, so you end up checking the value of the text box's size before it is actually resized. When you change tabs again, the text box is already resized, so you get the correct value.

Change the last few lines of your example form to look like this and it will become apparent:

            this.textBox1.SizeChanged += TextboxSizeChanged;
        }

        //Tab Selected
        private void tabControl1_Selected(object sender, EventArgs e)
        {
            System.Diagnostics.Debug.WriteLine("tab selected");
            this.Text = "TextBox Width: " + this.textBox1.Width.ToString();
        }

        private void TextboxSizeChanged(object sender, EventArgs e)
        {
            System.Diagnostics.Debug.WriteLine("Textbox resized");
        }
OwenP
Thanks for the example.
Gary Willoughby
+1  A: 

If you modify your code a little by adding an event handler to the textbox1.Resize event you will see what happens. The tabPage1.Selected event occurs before the controls in the tab page is resized so when you check the width of the textbox you are checking it before it is resized.

Normally this wouldn't be a problem, for the resizing is done properly afterwards, but I guess that you will be using the size of the textbox for something?

You should be able to write your own TabControl that fixes this problem, but you will have to experiment to see what works here.

Rune Grimstad