In my C# application, I populate a FlowLayoutPanel (FLP) with a list of 324 instances of a custom User Control (UC), with the UC containing a number of text fields and a small (10x10) panel, which is filled with an ellipse. After populating the FLP and scrolling from the top to the bottom of the FLP, only the first 282 UCs have the ellipse visible, and the rest of the last 82 UCs don't. However, if I scroll right to the bottom of the FLP, and re-populate the 324 UCs into the FLP, all UCs have the ellipse visible.
However and what's more, when I debug the FLP population process (loop), and inspect any one of the 82 UCs in the Local tab, and inspect the panel where the ellipse is drawn without doing anything else, the ellipse of the inspected UC then becomes visible when I scroll down to that UC once the FLP is populated. For me this is bizarre behavior, and I hope some of the experts out there can shed light on this.
I've spent days to figure out this problem, so any help from you experts would be greatly appreciated. Following are the approaches that I have tried, but all have failed to resolve the issue:
- Populate a PictureBox in the UC with a PNG instead of drawing an ellipse.
- Populate a PictureBox in the UC with a PNG after the main FLP population loop.
- Force scroll to the end of FLP after population, then back up to the top of the FLP.
- Only populate the FLP with a subset of the 324 UCs, like suggested in this post: Fake-scrolling containers with very many controls. This partially works, but does introduce flickering when scrolling through the FLP, since UCs are continuously being created, populated and destroyed.
Below are some screenshots and code snippets. This is the code snippet to populate the FLP with the 324 UCs:
this.Invoke(new Action(() =>
{
int i = 1;
foreach (var contact in (ContactsList.ListOfContacts))
{
ContactsListItem cliUc = new ContactsListItem()
{
Phone = contact.Phone.ToString(),
ContactName = contact.ContactName.ToString(),
Code = contact.Code.ToString(),
Flagged = contact.Flagged
};
cliUc.Colored();
cliList.Add(cliUc);
}
// REFRESH FlowLayoutPanel with list of ContactListItems from above.
this.custFlowLayout.Visible = false;
this.custFlowLayout.SuspendLayout();
// This may be tasked to a background thread so the flowlayoutpanel can appear sooner.
foreach (ContactsListItem contactsListItemOld in this.custFlowLayout.Controls)
{
contactsListItemOld.Dispose();
}
//Move to catch block, when error handling.
this.custFlowLayout.Controls.Clear();
this.custFlowLayout.Controls.AddRange(cliList.ToArray());
this.custFlowLayout.ResumeLayout(false);
this.custFlowLayout.Visible = true;
}));
This is the code snippet which draws the ellipse in the UC:
private void panelFlagged_Paint(object sender, PaintEventArgs e)
{
if (_flagged)
{
//this.picBoxStatus.Image = Properties.Resources.status_red;
Graphics g = panelFlagged.CreateGraphics();
SolidBrush sb = new SolidBrush(Color.Red);
g.FillEllipse(sb, 0, 0, 10, 10);
}
else
{
//this.picBoxStatus.Image = Properties.Resources.status_gray;
Graphics g = panelFlagged.CreateGraphics();
SolidBrush sb = new SolidBrush(Color.Gray);
g.FillEllipse(sb, 0, 0, 10, 10);
}
return;
}
This is the code snippet of the custom FLP and scrolling event for the FLP:
public class CustomFlowLayout : FlowLayoutPanel
{
public CustomFlowLayout()
{
// May be related to improved performance.
this.DoubleBuffered = true;
this.SetStyle(ControlStyles.UserPaint, true);
this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
this.SetStyle(ControlStyles.DoubleBuffer, true);
// Set this properties of this custom FlowLayoutPanel.
this.AutoScroll = false;
this.AutoSize = false;
this.WrapContents = false;
this.FlowDirection = FlowDirection.TopDown;
}
protected override void OnScroll(ScrollEventArgs se)
{
// DoEvents eliminates flickering while scrolling the panel.
Application.DoEvents();
// PerformaLayout ensures all child user controls added to this Controls are visible.
this.PerformLayout();
// INVESTIGATE following need further investigation.
base.OnScroll(se);
}
}
Screenshot shows the cutoff of the UCs which successfully display the drawn ellipse, and then rest of the 82 UCs don't:
Screenshot with 82 UCs not displaying drawing
Screenshot shows the one UC I inspected at debug time which does show the drawn ellipse, while the rest of the 82 UCs don't:
Screenshot with debugged 1 of 82 UCs displaying drawing
Edit: And now the problem is also happening on a new label I introduced into the UC (the original ellipse problem was solved by the first comment below):