我创建了一个用户控件,其中包含一个带有2个TabPages的TabControl。子控件在两个TabPage上的位置均通过用户控件的Layout
事件以编程方式进行调整。
问题是,调用事件时尚未绘制第二个TabPage,因此此TabPage的大小和ClientSize错误。
我该如何解决?
我已经尝试使用var oHandle = tabpage.Handle
和tabctrl.SelectedTab = each tabpage
进行循环以强制创建TabPage,但这并没有帮助。
编辑#1
我发现了在VS Designer中观察到的第一个“错误”:
当您在窗体上拖动TabControl
并在设计器中调整其大小时,当前可见的TabPage
的大小将被更新。但是所有其他选项卡的大小都没有。它们保持不变,直到对任何控件进行任何其他更改(已测试!)。
我承认这种情况很少见,因此通常会更新大小,但我认为这是TabControl
中的设计缺陷。
在运行时调整TabControl的大小时,此设计缺陷变得非常重要!这是repro的最小示例(没有UC,只有Form中的TabControl):
Form1.cs:
public Form1 ()
{
InitializeComponent ();
Debug.Print ("ctor before resize");
Debug.Print ("TC: " + tabControl1.Size);
Debug.Print ("T1: " + tabPage1.Size);
Debug.Print ("T2: " + tabPage2.Size);
tabControl1.Size = tabControl1.Size + new Size (10, 10);
Debug.Print ("ctor after resize");
Debug.Print ("TC: " + tabControl1.Size);
Debug.Print ("T1: " + tabPage1.Size);
Debug.Print ("T2: " + tabPage2.Size);
}
private void Form1_Load (object sender, EventArgs e)
{
... same as ctor, prints adapted ("load before/after resize)
}
private void Form1_Layout (object sender, LayoutEventArgs e)
{
Debug.Print ("Layout");
}
private void button1_Click (object sender, EventArgs e)
{
... same as ctor, prints adapted ("button before/after resize)
}
Form1.Designer.cs :(已删除不相关的部分)
private void InitializeComponent ()
{
this.tabControl1 = new System.Windows.Forms.TabControl ();
this.tabPage1 = new System.Windows.Forms.TabPage ();
this.tabPage2 = new System.Windows.Forms.TabPage ();
this.button1 = new System.Windows.Forms.Button ();
this.tabControl1.SuspendLayout ();
this.SuspendLayout ();
//
this.tabControl1.Controls.Add (this.tabPage1);
this.tabControl1.Controls.Add (this.tabPage2);
this.tabControl1.Size = new System.Drawing.Size (300, 120);
//
this.tabPage1.Size = new System.Drawing.Size (292, 91);
//
this.tabPage2.Size = new System.Drawing.Size (292, 91);
//
this.button1.Click += new System.EventHandler (this.button1_Click);
//
this.AutoScaleDimensions = new System.Drawing.SizeF (96F, 96F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
this.ClientSize = new System.Drawing.Size (384, 262);
this.Controls.Add (this.tabControl1);
this.Controls.Add (this.button1);
this.Load += new System.EventHandler (this.Form1_Load);
this.tabControl1.ResumeLayout (false);
this.ResumeLayout (false);
}
private System.Windows.Forms.TabControl tabControl1;
private System.Windows.Forms.TabPage tabPage1;
private System.Windows.Forms.TabPage tabPage2;
private System.Windows.Forms.Button button1;
调试打印:
ctor before resize
TC: {Width=300, Height=120}
T1: {Width=292, Height=91}
T2: {Width=292, Height=91}
Layout
Layout
ctor after resize
TC: {Width=310, Height=130}
T1: {Width=292, Height=91} (wrong)
T2: {Width=292, Height=91} (wrong)
Load before resize
TC: {Width=310, Height=130}
T1: {Width=302, Height=101} (now correct because updated after ctor)
T2: {Width=302, Height=101} (now correct because updated after ctor)
Layout
Layout
Load after resize
TC: {Width=320, Height=140}
T1: {Width=312, Height=111} (correct because visible)
T2: {Width=302, Height=101} (wrong again)
Layout
(TabPage1 selected, TabPage2 is not updated)
button before resize
TC: {Width=320, Height=140}
T1: {Width=312, Height=111}
T2: {Width=302, Height=101} (still wrong: TabPage2 HAS NOT BEEN UPDATED WHILE THE UI-THREAD WAS IDLE)
Layout
Layout
button after resize
TC: {Width=330, Height=150}
T1: {Width=322, Height=121}
T2: {Width=302, Height=101} (even more wrong)
(TabPage1 selected, TabPage2 is not updated)
button before resize
TC: {Width=330, Height=150}
T1: {Width=322, Height=121}
T2: {Width=302, Height=101} (still wrong)
Layout
Layout
button after resize
TC: {Width=340, Height=160}
T1: {Width=332, Height=131}
T2: {Width=302, Height=101} (again more wrong)
(TabPage2 selected, now TabPage1 is not updated)
button before resize
TC: {Width=340, Height=160}
T1: {Width=332, Height=131}
T2: {Width=332, Height=131} (now correct because visible)
Layout
Layout
button after resize
TC: {Width=350, Height=170}
T1: {Width=332, Height=131} (now wrong)
T2: {Width=342, Height=141} (still correct because visible)
基于此行为,我目前唯一的解决方案是每次调用UpdateLayout()
时都调用UC的tabControl1_SelectedIndexChanged (..)
函数。
编辑#2
编辑#1的“解决方案”不起作用,原因是:
如果TabPages的宽度很小,则页面上的控件将垂直排列,从而导致各个TabPage的高度更高。 UC的整体高度取决于TabControl的高度,TabControl的高度取决于所有TabPages,因此UpdateLayout()
必须具有所有TabPages的正确大小,否则,稍后选择另一个选项卡时,UC高度将再次更改。 ,但在设计时就应该是正确的。
答案 0 :(得分:0)
我找到了一个非常简单的解决方案来获取正确的TabPages大小:
所有TabPage都属于同一个TabControl,因此,不管各个TabPage的Size
属性是什么,所有TabPage的大小都相同。
此外,总有一个Tabpage报告正确的大小,即当前选择的TabPage。
因此,每个TabPage的大小为TabControl.SelectedTab.Size
。