Search code examples
c#winformsscrollpaintonpaint

How to stop Paint events from stacking up


I'm creating an application to schedule different tasks. These are displayed by drawing rectangles on a panel. This has to be responsive. So I need to draw and invalidate on every size change. When I reach a maximum height of my planning panel it autoscrolls.

The problem is when I grab the scrollbar and start scrolling away for a bit, when I release the scrollbar my whole application and computer freezes.

Most likely this is due to the onpaint event being called on every little scroll and stacking up, leaving the application to hang until they are all done.

Now my question is: How would I be able to fix this? Possibly by keeping the paint event from being called multiple times, but how?

The method called by the paint event:

private void panelPlanning_Paint(object sender, PaintEventArgs e)
    {
        for (int i = 0; i < userList.Count; i++)
        {
            Label temp = new Label();
            temp.Text = userList[i].Text;
            temp.Width = panelUsers.Width;
            temp.Height = 50;
            temp.BorderStyle = BorderStyle.FixedSingle;
            temp.Location = new Point(0, i * 50);
            temp.TextAlign = ContentAlignment.MiddleCenter;
            panelUsers.Controls.Add(temp);

            foreach (FullTask task in taskList)
            {
                if (task.AssignedTo == userList[i].Text && task.StartDate != "" && task.DueDate != "")
                {
                    DateTime start = DateTime.ParseExact(task.StartDate, "dd/MM/yyyy", CultureInfo.InvariantCulture);
                    DateTime end = DateTime.ParseExact(task.DueDate, "dd/MM/yyyy", CultureInfo.InvariantCulture);
                    Brush brush;
                    if (task.Priority == Enums.priorities[2])
                    {
                        brush = Brushes.Yellow;
                    }
                    else if (task.Priority == Enums.priorities[1])
                    {
                        brush = new SolidBrush(Color.FromArgb(255, 0, 80, 123));
                    }
                    else
                    {
                        brush = Brushes.Red;
                    }

                    panelPlanning.CreateGraphics().FillRectangle(brush, new Rectangle((start.Subtract(dtPickerStart.Value).Days + 1) * labelDaysWidth, i * 50, (end.Subtract(start).Days + 1) * labelDaysWidth, 25));
                }
            }
        }
    }

Solution

  • You are adding new Label controls on every single paint event. Don't do this:

          // Label temp = new Label();
          // temp.Text = userList[i].Text;
          // temp.Width = panelUsers.Width;
          // temp.Height = 50;
          // temp.BorderStyle = BorderStyle.FixedSingle;
          // temp.Location = new Point(0, i * 50);
          // temp.TextAlign = ContentAlignment.MiddleCenter;
          // panelUsers.Controls.Add(temp);
    

    Also, use the e.Graphics object supplied by the argument, not CreateGraphics,