C# TabControl填充会导致TabPage中的隐藏控件错误地重新排序
当C# TabControl填充会导致TabPage中的隐藏控件错误地重新排序,c#,winforms,tabcontrol,C#,Winforms,Tabcontrol,当选项卡Control的Padding属性更改时,尚未创建句柄的控件似乎被推到其父控件的底部。查看.NET源代码,Padding调用重新创建句柄(),似乎与此有关 下面是说明问题的代码。每个复选框的下方都有相应的标签。有些标签在开始时可见,有些则隐藏。选中person0复选框会使person0标签出现,但底部显示不正确。相反,person0标签应该显示在person0复选框的正下方,这是它添加到FlowLayoutPanel的顺序。见截图 该代码提供了一个booldoworkaround选项,但
选项卡Control
的Padding
属性更改时,尚未创建句柄的控件似乎被推到其父控件的底部。查看.NET
源代码,Padding
调用重新创建句柄()代码>,似乎与此有关
下面是说明问题的代码。每个复选框
的下方都有相应的标签
。有些标签在开始时可见,有些则隐藏。选中person0
复选框会使person0
标签出现,但底部显示不正确。相反,person0标签应该显示在person0复选框的正下方,这是它添加到FlowLayoutPanel
的顺序。见截图
该代码提供了一个booldoworkaround
选项,但必须有更好的方法。强制使用CreateControl()
创建所有句柄
,似乎也不正确
使用系统;
使用System.Collections.Generic;
使用系统图;
使用System.Linq;
使用System.Windows.Forms;
命名空间Windows窗体应用程序3{
公共类TabControl3:TabControl{
private bool doWorkaround=false;//设置为true以防止错误
受保护的覆盖无效OnFontChanged(事件参数e){
基数(e);
int h=(int)this.Font.Height;
SetPadding(新点(h,h));//调用此函数会导致控件重新排序错误
}
///设置填充将导致TabControl重新创建所有句柄,这将导致隐藏的无把手控件重新排列。
公共虚拟无效设置填充(点pt){
//解决方案:从选项卡页中删除所有控件,然后在完成后将其添加回。
int n=TabPages.Count;
控件[][]arr=null;
如果(doWorkaround){
arr=新控件[n][];
对于(int i=0;i
我使用.NET 3.5,4,4.52进行了测试,发现这三个版本的行为都相同。覆盖选项卡控件的OnControlAdded
,并添加base.OnControlAdded(e);如果(e.Control是TabPage){e.Control.Controls.OfType().ToList().ForEach(c=>c.CreateControl());}
。另外,在OnFontChanged
(您也可以使用OnLayout
)中,在base()
之后添加,如果(!this.IsHandleCreated)返回代码>。删除SetPadding()
中的所有内容,除了this.Padding=pt如果您有:var p=new Point(Font.Height,Font.Height),OnFontChanged中的code>可能会更好;如果(!Padding.Equals(p))设置Padding(p)代码>顺便说一句,您可以使用TableLayoutPanel而不是FlowLayoutPanel:)(或者一个用户控件而不是两个控件)覆盖TabControl的OnControlAdded
,并添加base.OnControlAdded(e);如果(e.Control是TabPage){e.Control.Controls.OfType().ToList().ForEach(c=>c.CreateControl());}
。另外,在OnFontChanged
(您也可以使用OnLayout
)中,在base()
之后添加,如果(!this.IsHandleCreated)返回代码>。删除SetPadding()
中的所有内容,除了this.Padding=pt如果您有:var p=new Point(Font.Height,Font.Height),OnFontChanged中的code>可能会更好;如果(!Padding.Equals(p))设置Padding(p)代码>顺便说一句,您可以使用TableLayoutPanel来代替
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
namespace WindowsFormsApplication3 {
public class TabControl3 : TabControl {
private bool doWorkaround = false; // set to true to prevent the bug
protected override void OnFontChanged(EventArgs e) {
base.OnFontChanged(e);
int h = (int) this.Font.Height;
SetPadding(new Point(h, h)); // calling this causes the Controls to re-order incorrectly
}
///<summary>Setting the padding causes the TabControl to recreate all the handles, which causes the hidden handleless controls to rearrange.</summary>
public virtual void SetPadding(Point pt) {
// Workaround solution: remove all controls from tab pages and then add them back after.
int n = TabPages.Count;
Control[][] arr = null;
if (doWorkaround) {
arr = new Control[n][];
for (int i = 0; i < n; i++) {
TabPage tp = TabPages[i];
arr[i] = tp.Controls.Cast<Control>().ToArray();
tp.Controls.Clear();
}
}
this.Padding = pt; // in the .NET source code, setting Padding calls RecreateHandle()
if (doWorkaround) {
for (int i = 0; i < n; i++)
TabPages[i].Controls.AddRange(arr[i]);
}
}
}
public class CheckBox2 : CheckBox {
public CheckBox2(String text, bool isChecked = false) : base() {
this.Text = text;
this.AutoSize = true;
this.Checked = isChecked;
}
}
public class Label2 : Label {
public Label2(String text) : base() {
this.Text = text;
this.AutoSize = true;
}
}
public class MyForm : Form {
TabControl tc = new TabControl3 { Dock = DockStyle.Fill };
public MyForm() {
this.Size = new System.Drawing.Size(600, 800);
this.StartPosition = FormStartPosition.CenterScreen;
TabPage tp1 = new TabPage("Page1");
FlowLayoutPanel p = new FlowLayoutPanel { FlowDirection = System.Windows.Forms.FlowDirection.TopDown, Dock = DockStyle.Fill };
p.Controls.Add(new CheckBox2("Person0"));
p.Controls.Add(new Label2("Person0") { Visible = false });
p.Controls.Add(new CheckBox2("Person1", true));
p.Controls.Add(new Label2("Person1"));
p.Controls.Add(new CheckBox2("Person2", true));
p.Controls.Add(new Label2("Person2"));
p.Controls.Add(new CheckBox2("Person3"));
p.Controls.Add(new Label2("Person3") { Visible = false });
p.Controls.Add(new CheckBox2("Person4"));
p.Controls.Add(new Label2("Person4") { Visible = false });
for (int i = 0; i < p.Controls.Count; i += 2) {
CheckBox cb = (CheckBox) p.Controls[i];
Label lb = (Label) p.Controls[i+1];
cb.CheckedChanged += delegate {
bool b = cb.Checked;
lb.Visible = b;
};
}
tp1.Controls.Add(p);
tc.TabPages.Add(tp1);
Controls.Add(tc);
}
protected override void OnLoad(EventArgs e) {
base.OnLoad(e);
this.Font = SystemFonts.MenuFont; // to trigger the bug
}
}
static class Program {
[STAThread]
static void Main() {
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MyForm());
}
}
}