4

I think vertical tearing is the proper term to describe what I'm seeing but here is an screenshot that shows the issue:

A scrolling panel with the a Label and an TextBox in a row at the top and then again below that but cut off as it degrades into a series of grey lines.

I thought the DoubleBuffered property could help with this but it neither setting it on my Form or inheriting TableLayoutPanel and setting it in the constructor seem to have any effect.

I apologize for the following long block of code, but I felt I should include a complete example that demonstrates the issue. You should just be able to copy it and run it to replicate my issue:

public class ScrollTearingDemo : Form
{
    private const int ROW_COUNT = 20;
    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new ScrollTearingDemo());
    }

    /// <summary>
    /// Required designer variable.
    /// </summary>
    private System.ComponentModel.IContainer components = null;
    private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1;

    public ScrollTearingDemo()
    {
        InitializeComponent();
        this.initializeTable();
    }

    /// <summary>
    /// Clean up any resources being used.
    /// </summary>
    /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
    protected override void Dispose(bool disposing)
    {
        if (disposing && (components != null))
        {
            components.Dispose();
        }
        base.Dispose(disposing);
    }

    // Moved this here to encapsulate demo in single source file
    /// <summary>
    /// Required method for Designer support - do not modify
    /// the contents of this method with the code editor.
    /// </summary>
    private void InitializeComponent()
    {
        this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
        //this.tableLayoutPanel1 = new BufferedTableLayoutPanel();
        this.SuspendLayout();
        // 
        // tableLayoutPanel1
        // 
        this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
        this.tableLayoutPanel1.AutoScroll = true;
        this.tableLayoutPanel1.CellBorderStyle = System.Windows.Forms.TableLayoutPanelCellBorderStyle.Single;
        this.tableLayoutPanel1.ColumnCount = 2;
        this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
        this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
        this.tableLayoutPanel1.Dock = DockStyle.Fill;
        this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0);
        this.tableLayoutPanel1.Name = "tableLayoutPanel1";
        this.tableLayoutPanel1.TabIndex = 0;
        // 
        // ScrollTearingDemo
        // 
        this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
        this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
        this.ClientSize = new System.Drawing.Size(284, 262);
        this.Controls.Add(this.tableLayoutPanel1);
        this.DoubleBuffered = true;
        this.Name = "ScrollTearingDemo";
        this.Text = "ScrollTearingDemo";
        this.ResumeLayout(false);

    }

    private void initializeTable()
    {
        // There is one more empty row to take up any extra space
        // in the event the number of rows does not fill the table.
        this.tableLayoutPanel1.RowCount = ROW_COUNT + 1;

        for(int j = 0; j < ROW_COUNT;j++)
        {
            Label markerLabel = new Label();
            markerLabel.Dock = System.Windows.Forms.DockStyle.Fill;
            markerLabel.TextAlign = ContentAlignment.MiddleRight;
            markerLabel.Name = "Label " + j;
            markerLabel.Text = markerLabel.Name;

            TextBox inputItem = new TextBox();
            inputItem.Dock = DockStyle.Fill;
            inputItem.Name = "Input " + j;
            inputItem.Text = inputItem.Name;
            inputItem.TextAlign = HorizontalAlignment.Right;
            inputItem.CausesValidation = true;

            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.AutoSize, 25F));

            this.tableLayoutPanel1.Controls.Add(markerLabel, 0, j);
            this.tableLayoutPanel1.Controls.Add(inputItem, 1, j);
        }

        // Row style for the empty filler row.
        this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 0F));

        this.ResumeLayout();
    }
}

The project this is for is limited to C# 2.0.

Fr33dan
  • 4,227
  • 3
  • 35
  • 62
  • 3
    TableLayoutPanel is a very evil control. It lulls programmers into believing that they can use it to implement their own grid control. It can't, use a DataGridView instead. The paint artifact is caused by the "Show window content while scrolling" option. It is a system option so you can't reasonably turn it off. The workaround in [this answer](http://stackoverflow.com/questions/3718380/winforms-double-buffering/3718648#3718648) solves your problem. – Hans Passant Jul 16 '14 at 15:30
  • @HansPassant True, Now that I think about it every time I try use it I end up having to use something else in the end for one reason or another. How many times will I try the water before I realize the well is poisoned? The workaround gets the job done for now but I will probably take your advice and switch to a DataGridView. – Fr33dan Jul 16 '14 at 15:39

0 Answers0