Niall
Niall

Reputation: 1621

DGV CellPainting behaving unexpectedly

I am displaying a list of hours in a DataGridView and would like to shade those hours which fall outside of business hours. I am trying to do this using CellPainting, however I am getting weird results. Could someone please explain what I am doing wrong here?

private void dgvItemView_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
{
    switch (_formType)
    {
        case FormType.DayView:
            TimeSpan openTime = iFlow.Properties.Settings.Default.BusinessHourOpen;
            TimeSpan closeTime = iFlow.Properties.Settings.Default.BusinessHourClose;

            DataGridViewCell cell = this.dgvItemView[e.ColumnIndex, e.RowIndex];

            if (cell.RowIndex < openTime.Hours || cell.RowIndex > closeTime.Hours)
            {
                e.Graphics.FillRectangle(new SolidBrush(Color.FromArgb(25, Color.Red)), e.ClipBounds);
            }
            break;
    }
}

However this code results in a gradient effect, as follows:

Form

Which I really don't understand. The shading also disappears and re-appears when I scroll up and down, depending on how much I scroll by.

So could someone please explain what I am doing wrong here? I am also going to need to paint partial blocks in case business hours are not on the hour e.g. 08:45 to 17:30, so I can't just change the cell's BackColor to achieve this.

Upvotes: 2

Views: 569

Answers (1)

Rotem
Rotem

Reputation: 21917

e.ClipBounds refers to the entire visible part of the DataGridView.
What you're essentially doing is painting multiple transparent layers over the entire visible DataGridView area, resulting in a gradient effect as you scroll.

You should be using e.CellBounds instead.

Another issue, unrelated to your problem, is that you are leaking GDI handles from the SolidBrush. Dispose() of your SolidBrush after painting, or better yet, use a using statement as such:

using (var sb = new SolidBrush(Color.FromArgb(25, Color.Red)))
{
    e.Graphics.FillRectangle(sb , e.CellBounds);
}

edit:

You must also set e.Handled to true after painting, to prevent the system from painting over your work.

From MSDN:

If you manually paint the cell, set the HandledEventArgs.Handled property to true. If you do not set HandledEventArgs.Handled to true, the cell will paint over your customizations.

Upvotes: 2

Related Questions