C#Winforms标签页大小和ClientSize错误

时间:2019-05-21 15:55:21

标签: c# winforms size tabcontrol tabpage

我创建了一个用户控件,其中包含一个带有2个TabPages的TabControl。子控件在两个TabPage上的位置均通过用户控件的Layout事件以编程方式进行调整。
问题是,调用事件时尚未绘制第二个TabPage,因此此TabPage的大小和ClientSize错误。

我该如何解决?
我已经尝试使用var oHandle = tabpage.Handletabctrl.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高度将再次更改。 ,但在设计时就应该是正确的。

1 个答案:

答案 0 :(得分:0)

我找到了一个非常简单的解决方案来获取正确的TabPages大小:

所有TabPage都属于同一个TabControl,因此,不管各个TabPage的Size属性是什么,所有TabPage的大小都相同。
此外,总有一个Tabpage报告正确的大小,即当前选择的TabPage。
因此,每个TabPage的大小为TabControl.SelectedTab.Size