使用 TableLayoutPanel 渲染生成的表格需要很长时间才能完成 [英] Rendering a generated table with TableLayoutPanel taking too long to finish

查看:25
本文介绍了使用 TableLayoutPanel 渲染生成的表格需要很长时间才能完成的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的程序在概念上非常简单 - 它允许用户在保龄球比赛中记录分数,并通过记分牌向玩家显示分数.

My program is pretty straight forward in concept - it allows a user to take scores during bowling tournaments, as well as showing the players the scores through a scoreboard.

有一个计分表表格,他们可以在其中输入分数,还有一个计分板表格,按部门向玩家显示分数.记分板在与主程序不同的线程中运行.

There's a score sheet form in which they enter scores, and a scoreboard form that shows the scores to the players, by division. The scoreboard is run in a different thread than the main program.

记分板由一个 TableLayoutPanel 组成,我以编程方式操作它来表示要显示的分数表.我的问题是表格渲染需要很长时间(尤其是对于一长串玩家).观看表格呈现本身的用户体验也不尽如人意.

The scoreboard is comprised of a TableLayoutPanel which I manipulate programmatically to represent a table of the scores to show. My issue with this is that it takes a long time (especially for a long list of players) for the table to render. The user experience of watching the table render itself leaves to be desired as well.

我测试了渲染文本框、标签和图片框的速度以减轻负载;文本框赢了,所以我把分数标签改成了文本框……但还是不够.

I tested the speed of rendering textboxes, labels, and picture boxes to lessen the load; textboxes won, so I changed the score labels to textboxes... but it's still not enough.

要浏览的内容很多,但如果有人知道我如何进一步加快记分牌的渲染速度,我会全神贯注.

It's a lot to look through, but if anyone has any idea how I could further speed up the rendering of the scoreboard, I'd be all ears/eyes.

这是我的流程分解.

调用方法(定时器每15秒调用一次):

The calling method (called every 15 seconds by a timer):

    private void switchBoard()
    {
        night = nights.GetNight(nightID);
        NightDay = night.Night_Date.ToString("ddd");
        //set the id of the division to show
        dtDivisions = scoreBoard.roll_display(dtDivisions);
        //get the row that is set to show
        DataRow[] drs = dtDivisions.Select("showing = 1");
        DataRow dr = drs[0];
        //update the title
        lbl_title.Top = 30;
        lbl_title.Text = (string)dr["title"] + "'s Qualifying - " + NightDay;
        lbl_title.Width = this.Width;
        lbl_title.TextAlign = ContentAlignment.MiddleCenter;
        //SET UP THE TABLE
        //get number of columns (games) for selected night
        int Cols = games.GetCountGamesForTourNightByDivision(tourID, nightID, scoreBoard.ShowDivision) + 3; //ACCOUNT FOR HEADER COLS, RANK AND TOTALS
        //get number of rows (players) for selected night
        int Rows = players.GetCountPlayersForTourNightByDivision(TourID, nightID, scoreBoard.ShowDivision) + 1; //ACCOUNT FOR HEADER ROWS
        //generate the table
        GenerateTable(Cols, Rows);
        //generate the headers
        GenerateHeaders(tourID, nightID);
        //fill in the scores
        GenerateScoreLabels(tourID, nightID, scoreBoard.ShowDivision);
    }

生成表格:

    private void GenerateTable(int columnCount, int rowCount)
    {
        //Clear out the existing controls, we are generating a new table layout
        this.tblPnlScoreboard.Controls.Clear();

        //Clear out the existing row and column styles
        this.tblPnlScoreboard.ColumnStyles.Clear();
        this.tblPnlScoreboard.RowStyles.Clear();

        //setting up the row and column counts
        this.tblPnlScoreboard.ColumnCount = columnCount;
        this.tblPnlScoreboard.RowCount = rowCount;

        for (int x = 0; x < columnCount; x++)
        {
            //add a column
            if(x==0) //ranking column
            {
                this.tblPnlScoreboard.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute,30));
            }
            else if(x==1) //names
            {
                this.tblPnlScoreboard.ColumnStyles.Add(new ColumnStyle(SizeType.AutoSize));
            }
            else if(x==columnCount-1) //totals
            {
                this.tblPnlScoreboard.ColumnStyles.Add(new ColumnStyle(SizeType.AutoSize));
            }
            else //games
            {
                this.tblPnlScoreboard.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, (this.tblPnlScoreboard.Width - 130) / columnCount));
            }

            for (int y = 0; y < rowCount; y++)
            {
                //add rows.  Only do this once, when creating the first column
                if (x == 0)
                {
                    if(y==0)
                    {
                        this.tblPnlScoreboard.RowStyles.Add(new RowStyle(SizeType.Absolute, 50));
                    }
                    else
                    {
                        this.tblPnlScoreboard.RowStyles.Add(new RowStyle(SizeType.AutoSize));
                    }

                }
            }
        }
    }

生成标题:

    private void GenerateHeaders(int TourID, int NightID)
    {
        //get the players to display
        DataTable dtPlayers = players.GetPlayersForTourNightByDivision(tourID, nightID, scoreBoard.ShowDivision);

        int Row = 1; //0 is the header row for Games and so on
        foreach (DataRow dr in dtPlayers.Rows)
        {
            //create the label
            Label lblPlayer = new Label();
            lblPlayer.Name = dr["ID"].ToString(); //name is the ID of the player
            lblPlayer.Text = dr["player_name"].ToString(); //the text is the name of the player
            lblPlayer.BackColor = Color.Transparent;
            lblPlayer.Font = new Font("Microsoft Sans Serif", 25, FontStyle.Bold);
            lblPlayer.TextAlign = ContentAlignment.MiddleLeft;
            lblPlayer.AutoSize = true;
            lblPlayer.Height = tblPnlScoreboard.GetRowHeights()[Row];
            //add the label to the table
            this.tblPnlScoreboard.Controls.Add(lblPlayer, 1, Row);

            //create the Total label
            Label lblTotal = new Label();
            lblTotal.Name = "lbl_total"; //name is arbitrary in this context
            lblTotal.Text = dr["Total"].ToString(); //the text is the total
            lblTotal.BackColor = Color.Transparent;
            lblTotal.Font = new Font("Microsoft Sans Serif", 25, FontStyle.Bold);
            lblTotal.TextAlign = ContentAlignment.MiddleLeft;
            lblTotal.AutoSize = true;
            lblTotal.Height = tblPnlScoreboard.GetRowHeights()[Row];
            //add the label to the table
            this.tblPnlScoreboard.Controls.Add(lblTotal, tblPnlScoreboard.ColumnCount, Row);

            //increment the row index
            Row++;
        }

        //totals column
        Label lblTotals = new Label();
        //lblTotals.Width = this.tblPnlScoreboard.GetColumnWidths()[this.tblPnlScoreboard.ColumnCount - 1];
        lblTotals.Height = tblPnlScoreboard.GetRowHeights()[0];
        lblTotals.Name = "lbl_total"; //name is the ID of the Game
        lblTotals.Text = "Totals"; //text is the display name of the Game
        lblTotals.BackColor = Color.Transparent;
        lblTotals.ForeColor = Color.White;
        lblTotals.Font = new Font("Microsoft Sans Serif", 25, FontStyle.Bold);
        lblTotals.TextAlign = ContentAlignment.MiddleCenter;
        lblTotals.AutoSize = true;
        lblTotals.Anchor = (AnchorStyles.None);
        //add the label to the table
        this.tblPnlScoreboard.Controls.Add(lblTotals, this.tblPnlScoreboard.ColumnCount-1, 0);

        //get the games to display
        DataTable dtGames = games.GetGamesForTourNightByDivision(tourID, nightID, scoreBoard.ShowDivision);

        int Col = 2; //0 is the header column for rank, 1 is the header col for Players
        foreach (DataRow dr in dtGames.Rows)
        {
            //create the label
            Label lblGame = new Label();
            lblGame.Width = this.tblPnlScoreboard.GetColumnWidths()[Col];
            lblGame.Height = tblPnlScoreboard.GetRowHeights()[0];
            lblGame.Name = dr["ID"].ToString(); //name is the ID of the Game
            lblGame.Text = dr["disp_name"].ToString().Replace("Game ", ""); //text is the display name of the Game
            lblGame.BackColor = Color.Transparent;
            lblGame.ForeColor = Color.White;
            lblGame.Font = new Font("Microsoft Sans Serif", 25, FontStyle.Bold);
            lblGame.TextAlign = ContentAlignment.MiddleCenter;
            lblGame.Anchor = (AnchorStyles.None);
            //add the label to the table
            this.tblPnlScoreboard.Controls.Add(lblGame, Col, 0);
            //increment the column index
            Col++;
        }
    }

最后,生成分数:

    private void GenerateScoreLabels(int TourID, int NightID, int DivID)
    {
        //get the id of the playergames record
        //expl: each player/game pair has a unique ID - these IDs will be used to update the scores
        Players players = new Players();
        DataTable dtScores = players.GetPlayerGamesIDsForTourNightByDivision(TourID, NightID, scoreBoard.ShowDivision);
        Divisions Divs = new Divisions();
        DataTable dtColors = Divs.GetDivisionScoreboardColors(DivID);

        foreach (DataRow dr in dtScores.Rows)
        {
            //find the coordinates in the table, where the textbox should be added
            int col = FindX((int)dr["fk_game_id"]);
            int row = FindY((int)dr["fk_player_id"]);

            if (col > 0 && row > 0)
            {                   
                TextBox txt_score = new TextBox();
                txt_score.Name = dr["ID"].ToString(); //name of the control is the player/game ID
                txt_score.Text = dr["score"].ToString(); //the text in the control is the score
                txt_score.ForeColor = Color.Black;
                txt_score.Font = new Font("Microsoft Sans Serif", 25, FontStyle.Bold);
                txt_score.Width = this.tblPnlScoreboard.GetColumnWidths()[col];
                txt_score.Height = tblPnlScoreboard.GetRowHeights()[0];
                if(row % 2 == 0)
                {
                    txt_score.BackColor = Color.FromArgb((int)dtColors.Rows[0]["sb_even_row_color"]);
                }
                else
                {
                    txt_score.BackColor = Color.FromArgb((int)dtColors.Rows[0]["sb_odd_row_color"]);
                }
                txt_score.BorderStyle = BorderStyle.None;
                txt_score.TextAlign = HorizontalAlignment.Center;
                txt_score.Anchor = (AnchorStyles.Top);

                this.tblPnlScoreboard.Controls.Add(txt_score, col, row);

                //start the switchboard timer
                ttmr_switch.Enabled = true;
            }
        }
    }

在 TableLayoutPanel 的 CellPaint 事件上,我有这些过程:

On the CellPaint event of the TableLayoutPanel, I have these processes:

    private void tblPnlScoreboard_CellPaint(object sender, TableLayoutCellPaintEventArgs e)
    {
        Graphics g = e.Graphics;
        Rectangle r = e.CellBounds;
        SolidBrush sb = GetBrushFor(e.Row, e.Column, scoreBoard.ShowDivision);

        g.FillRectangle(sb, r);
        sb.Dispose();
    }

颜色选择:

    private SolidBrush GetBrushFor(int row, int column, int DivID)
    {
        DataTable dt_colors = divisions.GetDivisionScoreboardColors(DivID);

        if (row == 0)
        {   //column headers
            SolidBrush brush = new SolidBrush(Color.FromArgb((int)dt_colors.Rows[0]["sb_column_header_color"]));
            return brush;
        }
        else
        {   
            if(row % 2 == 0) //even row
            {
                SolidBrush brush = new SolidBrush(Color.FromArgb((int)dt_colors.Rows[0]["sb_even_row_color"]));
                return brush;
            }
            else //odd row
            {
                SolidBrush brush = new SolidBrush(Color.FromArgb((int)dt_colors.Rows[0]["sb_odd_row_color"]));
                return brush;
            }
        }
    }

推荐答案

有些人建议您使用适当的技术".我宁愿说正确使用技术".即使这种奇怪(抱歉)的设计/实现选择也可以更快地工作,如下面的代码所示,正如您所看到的,它正在处理每秒 10 次重建包含 100 行 x 10 列的表 - 没什么大不了的与专业网格相比,但与原始实现相去甚远.要点:
1. 用Suspend/ResumeLayout 封闭表格重建,以避免在此过程中进行密集的重新计算.
2. 使用自定义双缓冲TableLayoutPanel 避免闪烁.
3. 自定义绘制数据单元格以避免分配大量控件.

Some people suggested you to use a "proper technology". I would rather say "use properly the technology". Even this weird (sorry) design/implementation choice can be made to work much faster, as shown in the code below, which as you may see is handling rebuilding a table containing 100 rows x 10 columns 10 times per sec - not a big deal compared to professional grids, but far from the original implementation. Key points:
1. Enclose table rebuild with Suspend/ResumeLayout to avoid intensive recalculations during the process.
2. Use custom double buffered TableLayoutPanel to avoid flickering.
3. Custom paint the data cells to avoid allocating a lot of controls.

由于您提供给我们的代码中缺少与基本数据相关的部分,因此我无法为您提供完全相同的工作代码.希望你能认出它并将其映射到你的东西上.

Since essential data related parts are missing in the code you gave us, I can't provide you exactly the same working code. Hope you can recognize and map it to your stuff.

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

namespace Tests
{
    static class Program
    {
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new ScoreBoardForm { WindowState = FormWindowState.Maximized });
        }
    }

    class ScoreBoardForm : Form
    {
        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);

            players = new List<Player>();
            for (int i = 0; i < 100; i++)
                players.Add(new Player { ID = i + 1, Name = "P" + (i + 1), Total = random.Next(1000) });
            games = new List<Game>();
            for (int i = 0; i < 10; i++)
                games.Add(new Game { ID = i + 1, Name = "G" + (i + 1) });

            scoreBoardTable = new ScoreBoardTable { Dock = DockStyle.Fill, Parent = this };
            scoreBoardTable.Bounds = this.DisplayRectangle;
            UpdateScoreBoard();
            scoreBoardTable.CellPaint += OnScoreBoardTableCellPaint;

            updateTimer = new Timer { Interval = 100 };
            updateTimer.Tick += (_sender, _e) => UpdateScoreBoard();
            updateTimer.Start();
        }
        private void OnScoreBoardTableCellPaint(object sender, TableLayoutCellPaintEventArgs e)
        {
            int playerIndex = e.Row - 1, gameIndex = e.Column - 2;
            if (playerIndex >= 0 && playerIndex < players.Count && gameIndex >= 0 && gameIndex < games.Count)
            {
                using (var br = new SolidBrush(GetBackColor(e.Row)))
                    e.Graphics.FillRectangle(br, e.CellBounds);
                var score = GetScore(players[playerIndex], games[gameIndex]);
                var sf = new StringFormat { Alignment = StringAlignment.Far, LineAlignment = StringAlignment.Center };
                e.Graphics.DrawString(score.ToString(), defaultCellFont, Brushes.Black, e.CellBounds, sf);
            }
        }
        private int GetScore(Player player, Game game)
        {
            return random.Next(10000);
        }
        class ScoreBoardTable : TableLayoutPanel
        {
            public ScoreBoardTable() { DoubleBuffered = AutoScroll = true; }
        }
        TableLayoutPanel scoreBoardTable;
        Timer updateTimer;
        List<Player> players;
        List<Game> games;
        Random random = new Random();
        class Player
        {
            public int ID;
            public string Name;
            public int Total;
        }
        class Game
        {
            public int ID;
            public string Name;
        }
        private void UpdateScoreBoard()
        {
            scoreBoardTable.SuspendLayout();
            GenerateTable(games.Count + 3, players.Count + 1);
            GenerateHeaderCells();
            // Custom cell paint is much faster, but requires a good data model.
            // If you uncomment the following line, make sure to get rid of CellPaint. 
            //GenerateScoreCells();
            scoreBoardTable.ResumeLayout(true);
        }
        private void GenerateTable(int columnCount, int rowCount)
        {
            scoreBoardTable.Controls.Clear();
            scoreBoardTable.ColumnStyles.Clear();
            scoreBoardTable.RowStyles.Clear();
            scoreBoardTable.ColumnCount = columnCount;
            scoreBoardTable.RowCount = rowCount;

            // Columns
            // Ranking
            scoreBoardTable.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 30));
            // Name 
            scoreBoardTable.ColumnStyles.Add(new ColumnStyle(SizeType.AutoSize));
            // Games
            var percent = (columnCount - 3) / (float)columnCount;
            for (int col = 2; col < columnCount - 1; col++)
                scoreBoardTable.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, percent));
            // Totals
            scoreBoardTable.ColumnStyles.Add(new ColumnStyle(SizeType.AutoSize));

            // Rows
            // Header
            scoreBoardTable.RowStyles.Add(new RowStyle(SizeType.Absolute, 50));
            // Players
            for (int row = 1; row < rowCount; row++)
                scoreBoardTable.RowStyles.Add(new RowStyle(SizeType.AutoSize));
        }
        private void GenerateHeaderCells()
        {
            Color backColor = Color.DarkGray, foreColor;
            int row, col;
            // Header
            row = 0;
            foreColor = Color.White;
            col = 0;
            AddCell(row, col++, "rank", "", foreColor, backColor);
            AddCell(row, col++, "playerName", "Player", foreColor, backColor);
            foreach (var game in games)
                AddCell(row, col++, "gameName" + game.ID, game.Name, foreColor, backColor);
            AddCell(row, col, "totalColumn", "Totals", foreColor, backColor);
            // Rows
            foreColor = Color.Black;
            row++;
            foreach (var player in players)
            {
                backColor = GetBackColor(row);
                AddCell(row, 0, "playerRank_" + player.ID, "", foreColor, backColor, ContentAlignment.MiddleLeft);
                AddCell(row, 1, "playerName_" + player.ID, player.Name, foreColor, backColor, ContentAlignment.MiddleLeft);
                AddCell(row, scoreBoardTable.ColumnCount, "playerTotal_" + player.ID, player.Total.ToString(), foreColor, backColor, ContentAlignment.MiddleRight);
                row++;
            }
        }
        private void GenerateScoreCells()
        {
            var foreColor = Color.Black;
            int row = 1;
            foreach (var player in players)
            {
                var backColor = GetBackColor(row);
                int col = 2;
                foreach (var game in games)
                {
                    var score = GetScore(player, game);
                    AddCell(row, col, "score_" + player.ID + "_" + game.ID, score.ToString(), foreColor, backColor, ContentAlignment.MiddleRight, false);
                    col++;
                }
                row++;
            }
        }
        static readonly Font defaultCellFont = new Font("Microsoft Sans Serif", 25, FontStyle.Bold);
        private Label AddCell(int row, int col, string name, string text, Color foreColor, Color backColor, ContentAlignment textAlign = ContentAlignment.MiddleCenter, bool autoSize = true)
        {
            var label = new Label();
            label.Name = name;
            label.Text = text;
            label.BackColor = backColor;
            label.ForeColor = foreColor;
            label.Font = defaultCellFont;
            label.TextAlign = textAlign;
            label.AutoSize = autoSize;
            label.Margin = new Padding(0);
            label.Dock = DockStyle.Fill;
            scoreBoardTable.Controls.Add(label, col, row);
            return label;
        }
        static Color GetBackColor(int row)
        {
            if (row % 2 == 0) //even row
                return Color.Yellow;
            else //odd row
                return Color.LightGreen;
        }
    }
}

EDIT 这里是使用 DataGridView 的等效实现(注意,在相同的刷新率下,现在行数(播放器)增加了十倍):

EDIT And here is equivalent implementation using DataGridView (note that now the number of rows (players) are ten times more at the same refresh rate):

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

namespace Tests
{
    static class Program
    {
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new ScoreBoardForm { WindowState = FormWindowState.Maximized });
        }
    }

    class ScoreBoardForm : Form
    {
        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);

            players = new List<Player>();
            for (int i = 0; i < 1000; i++)
                players.Add(new Player { ID = i + 1, Name = "P" + (i + 1), Total = random.Next(1000) });
            games = new List<Game>();
            for (int i = 0; i < 10; i++)
                games.Add(new Game { ID = i + 1, Name = "G" + (i + 1) });

            InitScoreBoard();
            UpdateScoreBoard();

            updateTimer = new Timer { Interval = 100 };
            updateTimer.Tick += (_sender, _e) => UpdateScoreBoard();
            updateTimer.Start();
        }

        DataGridView scoreBoardTable;
        Timer updateTimer;
        List<Player> players;
        List<Game> games;
        Random random = new Random();
        class Player
        {
            public int ID;
            public string Name;
            public int Total;
        }
        class Game
        {
            public int ID;
            public string Name;
        }
        private int GetScore(Player player, Game game)
        {
            return random.Next(10000);
        }
        void InitScoreBoard()
        {
            scoreBoardTable = new DataGridView { Dock = DockStyle.Fill, Parent = this };
            scoreBoardTable.Font = new Font("Microsoft Sans Serif", 25, FontStyle.Bold);
            scoreBoardTable.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
            scoreBoardTable.MultiSelect = false;
            scoreBoardTable.CellBorderStyle = DataGridViewCellBorderStyle.None;
            scoreBoardTable.BackgroundColor = Color.Honeydew;
            scoreBoardTable.ForeColor = Color.Black;
            scoreBoardTable.AllowUserToAddRows = scoreBoardTable.AllowUserToDeleteRows = scoreBoardTable.AllowUserToOrderColumns = scoreBoardTable.AllowUserToResizeRows = false;
            scoreBoardTable.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells;
            scoreBoardTable.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.AllCells;
            scoreBoardTable.RowHeadersVisible = false;
            scoreBoardTable.EnableHeadersVisualStyles = false;
            var style = scoreBoardTable.DefaultCellStyle;
            style.SelectionForeColor = style.SelectionBackColor = Color.Empty;
            style = scoreBoardTable.ColumnHeadersDefaultCellStyle;
            style.SelectionForeColor = style.SelectionBackColor = Color.Empty;
            style.BackColor = Color.Navy;
            style.ForeColor = Color.White;
            style = scoreBoardTable.RowHeadersDefaultCellStyle;
            style.SelectionForeColor = style.SelectionBackColor = Color.Empty;
            style = scoreBoardTable.RowsDefaultCellStyle;
            style.SelectionForeColor = style.ForeColor = Color.Black;
            style.SelectionBackColor = style.BackColor = Color.Yellow;
            style = scoreBoardTable.AlternatingRowsDefaultCellStyle;
            style.SelectionForeColor = style.ForeColor = Color.Black;
            style.SelectionBackColor = style.BackColor = Color.LightGreen;
            scoreBoardTable.CellFormatting += OnScoreBoardCellFormatting;
        }
        private void UpdateScoreBoard()
        {
            scoreBoardTable.ColumnCount = 3 + games.Count;
            for (int c = 0; c < scoreBoardTable.ColumnCount; c++)
            {
                var col = scoreBoardTable.Columns[c];
                if (c == 0)
                {
                    col.Name = "Rank";
                    col.HeaderText = "";
                    col.AutoSizeMode = DataGridViewAutoSizeColumnMode.None;
                    col.Width = 48;
                }
                else if (c == 1)
                {
                    col.Name = "Player";
                    col.HeaderText = "Player";
                    col.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleLeft;
                }
                else if (c == scoreBoardTable.ColumnCount - 1)
                {
                    col.Name = "Totals";
                    col.HeaderText = "Totals";
                    col.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight;
                    //col.AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
                }
                else
                {
                    var game = games[c - 2];
                    col.Name = "Game_" + game.ID;
                    col.HeaderText = game.Name;
                    col.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight;
                    //col.AutoSizeMode = DataGridViewAutoSizeColumnMode.DisplayedCells;
                }
            }
            scoreBoardTable.RowCount = players.Count;
            scoreBoardTable.AutoResizeColumnHeadersHeight();
            scoreBoardTable.Invalidate();
        }
        private void OnScoreBoardCellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
        {
            var player = players[e.RowIndex];
            int col = e.ColumnIndex;
            if (col == 0)
                e.Value = "";
            else if (col == 1)
                e.Value = player.Name;
            else if (col == scoreBoardTable.ColumnCount - 1)
                e.Value = player.Total.ToString();
            else
            {
                var game = games[col - 2];
                e.Value = GetScore(player, game).ToString();
            }
            e.FormattingApplied = true;
        }
    }
}

这篇关于使用 TableLayoutPanel 渲染生成的表格需要很长时间才能完成的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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