I'm trying to custom paint a DataGridView, but I'm having trouble getting it to look right after the DataGridView is scrolled. There are lines that show up across my cells. The problem is that the paint event seems to not be redrawing the cells when the control is scrolled, so cells that were drawn at the edge of the form are not redrawn once they are scrolled to the center.
I can eliminate the problem by ignoring the fact that part of the cells on the edge of DataGridView are not displayed and drawing them as if they are fully visible, but that will make my application not look as nice.
My question is: Is there a better way for me to paint the DataGridView so that I can adjust my cell painting for partially displayed cells? I've looked through other questions and tried using other paint events, but I haven't been able to get anything to work.
Here is a simple program that demonstrates the problem I'm talking about.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
for (int i = 0; i < 256; i++)
dataGridView1.Rows.Add(new object[] { string.Format("Test_text_{0}", i) });
dataGridView1.Paint += DataGridView1_Paint;
dataGridView1.CellPainting += (s, e) => { if (e.RowIndex > 0 && e.ColumnIndex >= 0) e.Handled = true; };
}
private void DataGridView1_Paint(object sender, PaintEventArgs e)
{
Rectangle rect;
using (Brush gridBrush = new SolidBrush(dataGridView1.GridColor),
cellBrush = new SolidBrush(dataGridView1.DefaultCellStyle.BackColor),
textBrush = new SolidBrush(dataGridView1.DefaultCellStyle.ForeColor))
{
using (Pen gridLinePen = new Pen(gridBrush))
{
for (int row = 0; row < dataGridView1.Rows.Count; row++)
{
if (!dataGridView1.Rows[row].Displayed)
continue;
if (dataGridView1.Rows[row].Cells[0].Value != null)
{
//draw cell
rect = dataGridView1.GetCellDisplayRectangle(0, row, true);//Setting cutOverflow to false removes lines
e.Graphics.FillRectangle(cellBrush, rect);
e.Graphics.DrawLine(gridLinePen, rect.Left, rect.Bottom - 1, rect.Right - 1, rect.Bottom - 1);
e.Graphics.DrawLine(gridLinePen, rect.Right - 1, rect.Top, rect.Right - 1, rect.Bottom);
//add text
e.Graphics.DrawString(dataGridView1.Rows[row].Cells[0].Value.ToString(),
dataGridView1.DefaultCellStyle.Font, textBrush, rect.X + 4, rect.Y + 4);
}
else
//handle empty rows
e.Graphics.FillRectangle(gridBrush, dataGridView1.GetCellDisplayRectangle(0, row, true));
}
}
}
}
}
Designer code
partial class Form1
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <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);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.dataGridView1 = new System.Windows.Forms.DataGridView();
this.Column1 = new System.Windows.Forms.DataGridViewTextBoxColumn();
((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).BeginInit();
this.SuspendLayout();
//
// dataGridView1
//
this.dataGridView1.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
this.dataGridView1.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
this.Column1});
this.dataGridView1.Location = new System.Drawing.Point(46, 36);
this.dataGridView1.Name = "dataGridView1";
this.dataGridView1.Size = new System.Drawing.Size(184, 428);
this.dataGridView1.TabIndex = 0;
//
// Column1
//
this.Column1.HeaderText = "Column1";
this.Column1.Name = "Column1";
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(281, 522);
this.Controls.Add(this.dataGridView1);
this.Name = "Form1";
this.Text = "Form1";
((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).EndInit();
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.DataGridView dataGridView1;
private System.Windows.Forms.DataGridViewTextBoxColumn Column1;
}
Here's a screenshot