C#Winforms标签页大小和ClientSize错误 [英] C# Winforms Tabpage Size and ClientSize wrong

查看:126
本文介绍了C#Winforms标签页大小和ClientSize错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have created a user control that contains a TabControl with 2 TabPages. The position of the child controls on both TabPages is adapted programmatically in the Layout event of the user control.
The problem is, that the 2nd TabPage has not been drawn yet when the event is called and therefore this TabPage has a wrong Size and ClientSize.

我该如何解决?
我已经尝试使用var oHandle = tabpage.Handletabctrl.SelectedTab = each tabpage进行循环以强制创建TabPage,但这并没有帮助.

How can I work around that?
I tried a loop with var oHandle = tabpage.Handle and tabctrl.SelectedTab = each tabpage already to force the creation of the TabPages, but this hasn't helped.

编辑#1
我发现了在VS Designer中观察到的第一个错误":
当您在窗体上拖动TabControl,然后在设计器中调整其大小时,当前可见的TabPage的大小将被更新.但是所有其他标签页的大小都没有.它们保持不变,直到对任何控件进行任何其他更改(已测试!).
我承认这种情况很少见,因此通常会更新大小,但是我认为这是TabControl中的设计缺陷.

EDIT #1
I have found a first "bug" which is observed in the VS Designer:
When you drag a TabControl on the Form and then resize the it in the Designer, the size of the currently visible TabPage is updated. But the sizes of all other tabpages are not; they stay the same until any additional change is done on any control (tested!).
I admit that this situation is quite uncommon, so the sizes usually are updated, but nonetheless in my opinion it's a design flaw in the TabControl.

在运行时调整TabControl的大小时,此设计缺陷变得非常重要!这是repro的最小示例(没有UC,只有Form中的TabControl):

This design flaw becomes very relevant when the TabControl is resized at runtime! Here's a minimal example for repro (without UC, just a TabControl in a Form):

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 :(已删除不相关的部分)

Form1.Designer.cs: (irrelevant parts removed)

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)

基于此行为,我目前唯一的解决方案是在每次tabControl1_SelectedIndexChanged (..)调用时都调用UC的UpdateLayout()函数.

Based on this behaviour, the only solution that I currently have is calling the UpdateLayout() function of my UC on every call of tabControl1_SelectedIndexChanged (..).

编辑#2
编辑#1的解决方案"不起作用,原因是:
如果TabPages的宽度很小,则页面上的控件将垂直排列,从而导致各个TabPage的高度更高. UC的整体高度取决于TabControl的高度,该高度取决于所有TabPages,因此UpdateLayout()必须具有所有TabPages的正确大小,否则UC高度将在以后选择另一个选项卡时再次更改.在设计时就应该是正确的.

EDIT #2
The "solution" of Edit #1 does not work because:
If the TabPages have little width, the controls on the pages are arranged vertically, causing a greater height of the respective TabPage. The overall height of the UC depends on the height of the TabControl, whose height depends on all TabPages, so the UpdateLayout() needs to have correct sizes of all TabPages, otherwise the UC height would change again later when another tab is selected, but it should be correct already at design time.

推荐答案

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

I found a quite simple solution to get the correct size of the TabPages:

所有TabPage都属于同一个TabControl,因此,无论各个TabPage的Size属性怎么说,所有TabPage的大小都相同.
此外,总有一个TabPage报告正确的大小,即当前选择的TabPage.
因此,每个TabPage的大小为TabControl.SelectedTab.Size.

All TabPages belong to the same TabControl, thus all TabPages have the same size, no matter what the Size property of the respective TabPage says.
Additionally, there's allways one TabPage that reports the correct size, which is the currently selected TabPage.
Therefore the size of every TabPage is TabControl.SelectedTab.Size.


不幸的是,如果整个TabControl不可见,这将不起作用,可能是因为它被放置在当前未选中的另一个TabControlTabPage上.
但是,我找到了另一种解决方案,我将此问题发布为答案 .com/q/11276107/2505186>我可以强制*在选择*之前*强制TabControl的TabPage调整大小吗?,这实际上是我的一个重复问题.
该答案的相关部分:


Unfortunately this does NOT work if the whole TabControl is not visible, maybe because it's placed on a TabPage of another TabControl which is currently not selected.
However, I found another solution, which I posted as an answer on this question Can I force a TabControl's TabPages to resize *before* they're selected?, which actually is more or less a duplicate question of mine.
The relevant part of that answer:

[...]
您只需在代码中添加1行:

[...]
You have to add just 1 line to your code:

var oSize = i_oTabControl.DisplayRectangle.Size;

,并避免编译器对其进行优化:

and avoid that it's probably optimized away by the compiler:

[MethodImpl (MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)]
public static void TabControlForceUpdateOfTabpageSize (this TabControl i_oTabControl)
{
  if (i_oTabControl == null)
    return;
  var oSize = i_oTabControl.DisplayRectangle.Size;
}

[...]

这篇关于C#Winforms标签页大小和ClientSize错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆