代码之家  ›  专栏  ›  技术社区  ›  Loathing

TabControl填充会导致TabPage中的隐藏控件重新排序不正确

  •  0
  • Loathing  · 技术社区  · 4 年前

    控件 Handles Parent Control TabControl Padding 属性已更改。看着 .NET 源代码, 衬垫 打电话给 RecreateHandle();

    下面是说明问题的代码。每个 checkbox label 就在它下面。有些标签在开始时是可见的,有些是隐藏的。检查 person0 复选框使 个人0 FlowLayoutPanel . 见截图。

    代码提供了一个 bool doWorkaround 但一定有更好的办法。强迫所有 把手 将使用 CreateControl() 似乎也不正确。

    example

    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());
        }
    }
    }
    

    我用 .NET 3.5, 4, 4.52

    0 回复  |  直到 4 年前