0

I have a WinForms form with a dynamically generated TableLayoutPanel. During runtime I add or remove rows, so I set a maximum size and set it to autoscroll. All the rows and columns are auto-sized, and I added padding for the vertical scrollbar so that it doesn't end up overlapping the cells (and thus forcing the creation of a horizontal scrollbar, using (on form creation):

tableLayoutPanel_dataLogs.Padding = new Padding(0, 0, SystemInformation.VerticalScrollBarWidth, 0);

When there is not enough data to force an autscroll, it looks like this:

Proper appearance without autscroll

The problem is, when it does add the autoscroll, it introduces this odd graphical glitch:

Glitch appears with autoscroll

The glitch is that white line on the right side under the checkmark image and on the border above the checkmark. I assume this must have something to do with the scrollbar appearance settings, but I'm not quite sure what. Any ideas?

EDIT: add code for tableLayoutPanel:

// 
// tableLayoutPanel_dataLogs
// 
this.tableLayoutPanel_dataLogs.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
| System.Windows.Forms.AnchorStyles.Left) 
| System.Windows.Forms.AnchorStyles.Right)));
this.tableLayoutPanel_dataLogs.AutoSize = true;
this.tableLayoutPanel_dataLogs.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
this.tableLayoutPanel_dataLogs.CellBorderStyle = System.Windows.Forms.TableLayoutPanelCellBorderStyle.InsetDouble;
this.tableLayoutPanel_dataLogs.ColumnCount = 7;
this.tableLayoutPanel_dataLogs.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel_dataLogs.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel_dataLogs.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel_dataLogs.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel_dataLogs.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel_dataLogs.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel_dataLogs.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel_dataLogs.Controls.Add(this.checkBox_getAllDataLogs, 0, 0);
this.tableLayoutPanel_dataLogs.Controls.Add(this.label1, 1, 0);
this.tableLayoutPanel_dataLogs.Controls.Add(this.label2, 3, 0);
this.tableLayoutPanel_dataLogs.Controls.Add(this.label3, 5, 0);
this.tableLayoutPanel_dataLogs.Controls.Add(this.label5, 4, 0);
this.tableLayoutPanel_dataLogs.Controls.Add(this.label4, 2, 0);
this.tableLayoutPanel_dataLogs.Controls.Add(this.pictureBox1, 6, 0);
this.tableLayoutPanel_dataLogs.Location = new System.Drawing.Point(6, 445);
this.tableLayoutPanel_dataLogs.MaximumSize = new System.Drawing.Size(600, 144);
this.tableLayoutPanel_dataLogs.MinimumSize = new System.Drawing.Size(400, 56);
this.tableLayoutPanel_dataLogs.Name = "tableLayoutPanel_dataLogs";
this.tableLayoutPanel_dataLogs.Padding = new System.Windows.Forms.Padding(0, 0, System.Windows.Forms.SystemInformation.VerticalScrollBarWidth, 0);
this.tableLayoutPanel_dataLogs.RowCount = 1;
this.tableLayoutPanel_dataLogs.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel_dataLogs.Size = new System.Drawing.Size(420, 56);
this.tableLayoutPanel_dataLogs.TabIndex = 65;
this.tableLayoutPanel_dataLogs.Visible = false;

And here's the code that adds rows:

tableLayoutPanel_dataLogs.Visible = false;

tableLayoutPanel_dataLogs.SuspendLayout();

for (int i = 0; i < logCount; i++)
{
    //code that generates the data to populated not shown
    //...
    //created currentSerial, currentDateTime, currentEntriesCount

    tableLayoutPanel_dataLogs.RowCount++;
    tableLayoutPanel_dataLogs.RowStyles.Add(new RowStyle(SizeType.AutoSize));
    string row = (tableLayoutPanel_dataLogs.RowCount - 1).ToString("D2");
    string cbName = ControlNames.checkBoxSelectedName + row;
    tableLayoutPanel_dataLogs.Controls.Add(new CheckBox { Name = cbName, Text = String.Empty, Anchor = AnchorStyles.None, AutoSize = true }, 0, tableLayoutPanel_dataLogs.RowCount - 1);
    CheckBox cb = this.Controls.Find(cbName, true).First() as CheckBox;
    checkBoxes.Add(cb.Name,cb);
    cb.CheckedChanged += new System.EventHandler(this.checkBox_getAnyDataLog_CheckedChanged);

    tableLayoutPanel_dataLogs.Controls.Add(new Label() { Name = ControlNames.labelNumberName + row, Text = (tableLayoutPanel_dataLogs.RowCount - 1).ToString(), Anchor = AnchorStyles.None, Font = new System.Drawing.Font("Microsoft Sans Serif", 8F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))), AutoSize = true }, 1, tableLayoutPanel_dataLogs.RowCount - 1);
    tableLayoutPanel_dataLogs.Controls.Add(new Label() { Name = ControlNames.labelSerialName + row, Text = currentSerial, Anchor = AnchorStyles.None, Font = new System.Drawing.Font("Microsoft Sans Serif", 8F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))), AutoSize = true }, 2, tableLayoutPanel_dataLogs.RowCount - 1);
    tableLayoutPanel_dataLogs.Controls.Add(new Label() { Name = ControlNames.labelDateTimeName + row, Text = currentDateTime.ToString("MM/dd/yy HH:mm"), Anchor = AnchorStyles.None, Font = new System.Drawing.Font("Microsoft Sans Serif", 8F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))), AutoSize = true }, 3, tableLayoutPanel_dataLogs.RowCount - 1);
    tableLayoutPanel_dataLogs.Controls.Add(new Label() { Name = ControlNames.labelEntriesName + row, Text = currentEntriesCount, Anchor = AnchorStyles.None, Font = new System.Drawing.Font("Microsoft Sans Serif", 8F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))), AutoSize = true }, 4, tableLayoutPanel_dataLogs.RowCount - 1);

    string tbName = ControlNames.textBoxFileNameName + row;
    tableLayoutPanel_dataLogs.Controls.Add(new TextBox() { Name = tbName, Text = String.Empty, Enabled = false, Anchor = AnchorStyles.Left, Font = new System.Drawing.Font("Microsoft Sans Serif", 8F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))), AutoSize = true }, 5, tableLayoutPanel_dataLogs.RowCount - 1);
    TextBox tb = this.Controls.Find(tbName, true).First() as TextBox;
    tb.TextChanged += new System.EventHandler(this.textBoxFileName_TextChanged);

    tableLayoutPanel_dataLogs.Controls.Add(new PictureBox() { Name = ControlNames.pictureBoxName + row, Image = global::DataKey_Application.Properties.Resources.check_small, Text = "", Enabled = false, Visible = false, Margin = new System.Windows.Forms.Padding(0, 0, 0, 0), SizeMode = PictureBoxSizeMode.AutoSize, Anchor = AnchorStyles.Left }, 6, tableLayoutPanel_dataLogs.RowCount - 1);
    }

tableLayoutPanel_dataLogs.ResumeLayout(); 
tableLayoutPanel_dataLogs.PerformLayout();
Adam Hoffman
  • 109
  • 1
  • 14
  • 1
    TableLayoutPanel is *not* a grid control. Use DataGridView. – Hans Passant Jan 22 '15 at 22:56
  • Very helpful, and you're certainly correct, but considering I have everything working well except this issue with the TableLayoutPanel, I'd rather avoid a big re-factor to switch to DataGridView. Behind all the code are events that respond to/control the checkboxes, textBoxes, and those check-marks. Is there a way to get this working without the glitch as is? – Adam Hoffman Jan 22 '15 at 23:50

3 Answers3

0

When the vertical scroll appears the docking changes the widths on the table. Your minimum size probably doesn't allow for it to go as small as it is.

sk1tt1sh
  • 198
  • 1
  • 2
  • 11
  • I've tried changing the minimum size and this has no effect. I also tried changing the auto-size mode to "Grow and shrink". It was previously "Grow only". Glitch still appears. – Adam Hoffman Jan 22 '15 at 21:06
  • Just out of curiosity is it double buffered? Also how is the check mark added? It is an image within that cell or as the cell itself? – sk1tt1sh Jan 23 '15 at 00:30
  • I don't believe it's double-buffered (or at least, I didn't do anything to specifically implement a double buffer). I do `tableLayoutPanel.Visible = false` before I add/remove rows. then do a `PerformLayout` before making it visible again. The checkmark is a `PictureBox` added in during runtime, but I was getting the same glitch even before I added that column. – Adam Hoffman Jan 23 '15 at 00:47
  • When you say it was the same glitch prior to adding that column, do you mean that it was creating the white line on the "Save File Name" column? What's the parent control of the tablelayoutpanel? If you just add that object to a form without anything else does the glitch still occur? – sk1tt1sh Jan 23 '15 at 17:41
  • I tried switching to a double-buffered tableLayoutPanel, using code found [here](http://www.richard-banks.org/2007/09/how-to-create-flicker-free.html). No effect; the glitch still appears. – Adam Hoffman Jan 23 '15 at 18:24
  • Yeah, the white line was appearing in the "Save File Name" column. The parent is a custom UserControl that is contained inside a slightly modified TabControl. I made a new Form to try out your idea, and discovered that, yes the glitch does occur when it's in a separate form. It also seems to be related to the padding for the scrollbar, because on my first try, I forgot to add the padding, which resulted in a horizontal scrollbar appearing, and no glitch. When I added the padding in, the glitch came back. – Adam Hoffman Jan 23 '15 at 18:41
0

OK, time to excavate this and answer my own question (again). I came back to this issue because my tableLayoutPanel didn't resize properly when going from a long list (e.g. autoscroll needed) back to a small list. I took an idea from @Bioukh from here and dropped the tableLayoutPanel into a panel. The panel defines the max size of the tableLayoutPanel, which is docked inside with Dock = top and has autoscroll disabled. Just before I draw the table, I check its preferred height and enable autoscroll on the panel if it's going to be too big. When I clear the table, I also disable autoscroll on the panel. This ensures both that the table is displayed with a scrollbar when it should be (without a graphical glitch), and that the panel scrollbar disappears when the table is small.

After drawing the table:

tableLayoutPanel_dataLogs.ResumeLayout(); 
tableLayoutPanel_dataLogs.PerformLayout();
if (tableLayoutPanel_dataLogs.GetPreferredSize(new Size()).Height > panel1.Size.Height) 
    panel1.AutoScroll = true;
tableLayoutPanel_dataLogs.Visible = true;

Clearing the table:

tableLayoutPanel_dataLogs.SuspendLayout();

TableLayoutControlCollection controls = tableLayoutPanel_dataLogs.Controls;
for (int i = controls.Count - 1; i > 0; i--)
{
    if (tableLayoutPanel_dataLogs.GetCellPosition(controls[i]).Row != 0)
    {
        Control control = controls[i];
        if (control.Name.Contains(ControlNames.checkBoxSelectedName)) ((CheckBox)control).CheckedChanged -= new System.EventHandler(this.checkBox_getAnyDataLog_CheckedChanged);
        else if (control.Name.Contains(ControlNames.textBoxFileNameName)) ((TextBox)control).TextChanged -= new System.EventHandler(this.textBoxFileName_TextChanged);
        controls.Remove(control);
        control.Dispose();
    }
}

while (tableLayoutPanel_dataLogs.RowCount > 1)
{
    int row = tableLayoutPanel_dataLogs.RowCount - 1;
    tableLayoutPanel_dataLogs.RowStyles.RemoveAt(row);
    tableLayoutPanel_dataLogs.RowCount--;
}
tableLayoutPanel_dataLogs.Size = new System.Drawing.Size(420, 56);
tableLayoutPanel_dataLogs.Visible = false;
tableLayoutPanel_dataLogs.ResumeLayout();
tableLayoutPanel_dataLogs.PerformLayout();
panel1.AutoScroll = false;
panel1.PerformLayout();
checkBoxes.Clear();
Community
  • 1
  • 1
Adam Hoffman
  • 109
  • 1
  • 14
0

Why don't you use data grid. it's simple and doesn't glitch when you scroll since it's update is in real-time. Moreover, it has more features than tablelayoutpanel

  • 1
    I see you only have one reputation. This is better as a comment on the question, but absurdly the system doesn't allow for that until you have more reputation. Unfortunately, this is a 6 year old question so a dialog in the answer section is even less appropriate that normal. You should delete this before you lose rep from down votes. – Rodger Aug 13 '21 at 23:36