碎片化渲染动态TableLayoutPanel WF

Fragmented rendering dynamic TableLayoutPanel WF

我创建了一个 class 来设计动态 TableLayoutPanel,但在呈现期间 table 表现不佳。这是 class:

using System.Drawing;
using System.Windows.Forms;
using System.Collections.Generic;

namespace office_software.Table {
    class CalibrationTable : TableLayoutPanel {
        
        private readonly string[] header;
        private readonly List<Row> data;

        public CalibrationTable(TableLayoutPanel parent, string[] header, List<Row> data) {
            this.header = header;
            this.data = data;

            parent.SuspendLayout();

            TableLayoutPanel child = TableConstruction();
            if (parent.GetControlFromPosition(0, 1) != null) parent.Controls.Remove(parent.GetControlFromPosition(0, 1));
            parent.Controls.Add(child, 0, 1);

            parent.ResumeLayout(true);
        }

        private void CreateHeader(TableLayoutPanel parent) {
            for (int i = 0; i < header.Length; i++) parent.Controls.Add(new TableLable(FontStyle.Bold, header[i], 9.75F), i, 0);
        }

        private void CreateBody(TableLayoutPanel parent) {
            int j = 0;
            foreach (Row row in data) {
                for (int i = 0; i < row.values.Count; i++) {
                    parent.Controls.Add(new TableLable(FontStyle.Regular, row.values[i], 9.75F), i, j + 1);
                }
                j++;
            }
        }

        private TableLayoutPanel TableConstruction() {

            TableLayoutPanel table = new TableLayoutPanel {
                AutoSize = true,
                AutoScroll = true,
            };

            table.SuspendLayout();

            if (data?.Count > 0) {
                table.RowCount = data.Count + 1;
                table.ColumnCount = header.Length;
                table.CellBorderStyle = TableLayoutPanelCellBorderStyle.Single;
                table.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;

                for (int i = 0; i < table.ColumnCount; i++) table.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, (100 / table.ColumnCount)));
                for (int i = 0; i < table.RowCount; i++) table.RowStyles.Add(new RowStyle(SizeType.Absolute, 40F));
                
                CreateHeader(table);
                CreateBody(table);
            }
            else {
                table.RowCount = 1;
                table.ColumnCount = 1;
                table.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Bottom;
                table.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 50F));
                table.RowStyles.Add(new RowStyle(SizeType.Absolute, 50F));
                table.Controls.Add(new TableLable(FontStyle.Bold, "NESSUN ELEMENTO TROVATO", 15F), 0, 0);
            }

            table.ResumeLayout();

            return table;
        }
    }
}

这是 table 渲染过程中发生的情况。这种情况持续几秒钟。 “加载”后,table 会正常显示。

更新

这是class TableLable:

using System.Drawing;
using System.Windows.Forms;

namespace office_software.Table {
    class TableLabel : Label {
        public TableLabel(FontStyle style, string text, float size) {
            Text = text;
            AutoSize = true;
            Anchor = AnchorStyles.None;
            TextAlign = ContentAlignment.MiddleCenter;
            Font = new Font("Microsoft Sans Serif", size, style, GraphicsUnit.Point, 0);
        }
    }

为了完整起见,这是表单组件层次结构。我在 condainerPanel 内的 (col = 0, row = 1)

位置插入动态 table

设置 DoubleBuffered = true; 似乎解决了调整大小缓慢的问题:

class CalibrationTable : TableLayoutPanel {

    public class Row {
        public List<String> values;
    }

    class TableLabel : Label {
        public TableLabel(FontStyle style, string text, float size) {
            Text = text;
            AutoSize = true;
            Anchor = AnchorStyles.None;
            TextAlign = ContentAlignment.MiddleCenter;
            Font = new System.Drawing.Font("Microsoft Sans Serif", size, style, GraphicsUnit.Point, 0);
        }
    }

    private readonly string[] header;
    private readonly List<Row> data;

    public CalibrationTable(String[] header, List<Row> data)
        : base() {
        this.header = header;
        this.data = data;
        this.AutoSize = true;
        this.AutoScroll = true;
        this.Dock = DockStyle.Fill;
        this.DoubleBuffered = true; // this line is very important for speed

        TableConstruction(this);
    }

    private static void CreateHeader(CalibrationTable table) {
        String[] header = table.header;
        for (int i = 0; i < header.Length; i++) table.Controls.Add(new TableLabel(FontStyle.Bold, header[i], 9.75F), i, 0);
    }

    private static void CreateBody(CalibrationTable table) {
        List<Row> data = table.data;
        int j = 0;
        foreach (Row row in data) {
            for (int i = 0; i < row.values.Count; i++) {
                table.Controls.Add(new TableLabel(FontStyle.Regular, row.values[i], 9.75F), i, j + 1);
            }
            j++;
        }
    }

    private static void TableConstruction(CalibrationTable table) {

        table.SuspendLayout();
        if (table.data.Count > 0) {
            table.RowCount = table.data.Count + 1;
            table.ColumnCount = table.header.Length;
            table.CellBorderStyle = TableLayoutPanelCellBorderStyle.Single;
            //table.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;

            for (int i = 0; i < table.ColumnCount; i++) table.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, (100 / table.ColumnCount)));
            for (int i = 0; i < table.RowCount; i++) table.RowStyles.Add(new RowStyle(SizeType.Absolute, 40F));

            CreateHeader(table);
            CreateBody(table);
        }
        else {
            table.RowCount = 1;
            table.ColumnCount = 1;
            table.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Bottom;
            table.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 50F));
            table.RowStyles.Add(new RowStyle(SizeType.Absolute, 50F));
            table.Controls.Add(new TableLabel(FontStyle.Bold, "NESSUN ELEMENTO TROVATO", 15F), 0, 0);
        }

        table.ResumeLayout();
    }
}


[STAThread]
static void Main() {
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);

    Form fff = new Form();
    fff.Size = new Size(900, 800);
    fff.StartPosition = FormStartPosition.CenterScreen;

    String[] headers = "A,B,C,D,E,F,G,H,I,J".Split(',');
    List<CalibrationTable.Row> data = new List<CalibrationTable.Row>();
    int k = 0;
    for (int i = 0; i < 50; i++) {
        List<String> list = new List<String>();
        data.Add(new CalibrationTable.Row { values = list });
        for (int j = 0; j < headers.Length; j++) {
            list.Add(k.ToString());
            k++;
        }
    }
    CalibrationTable ct = new CalibrationTable(headers, data);
    fff.Controls.Add(ct);


    Application.Run(fff);
}