Populating a FlowLayoutPanel with a large number of controls and painting thumbnails on demand
Asked Answered
C

3

6

I'm trying to make an ImageListBox kind of control that will display a large numbers of thumbnails, like the one that Picasa uses.

This is my design:

I have a FlowLayoutPanel that is populated with a lot of UserControl objects, for example 4,000. Each UserControl is assigned a delegate for the Paint event. When the Paint event is called, it checks a memory cache for the thumbnail and if the image is not in cache, it retrieves it from the disk.

I have two problems that I'm trying to solve:

  1. It seems that WinForms will trigger a Paint event even if the UserControl is not in view. Only 10 or so controls are in fact in view, the rest are not (the FlowLayoutPanel.AutoScroll is set to true). As a result, it tries to retrieve thumbnails for all the images and that takes a long time.

  2. Adding the UserControl objects to the FlowLayoutPanel takes a somewhat long time, about 2-3 seconds. I can live with it but I'm wondering if there is a better way to do it than:

    UserControl[] boxes = new UserControl[N];
    // populate array
    panel.SuspendLayout();
    panel.Controls.AddRange(boxes);
    panel.ResumeLayout();
    
Cottontail answered 22/1, 2009 at 21:27 Comment(2)
Have allmost the same problem. Im working with "contracts" wich can have x rows (x controls in the fl-panel) and I see also the long time to fill the panel with all controls. 2-3 seconds for 200 items (not even 4000 as in your case). Ill "fav" this question for sure. ;)Macronucleus
Im allso using suspendlayout/resumelayout and visible true/false when filling objects.Macronucleus
O
7

To improve the speed of populating the FlowLayoutPanel with your user controls, disable layout updating while you add the controls.

Immediately before your loop, call SuspendLayout() and then at the end call ResumeLayout(). Make sure to use a try-finally to guarantee the ResumeLayout() runs even if an exception occurs.

Orel answered 24/1, 2009 at 20:29 Comment(0)
S
3

I wouldn't add that many user controls. Rather, I'd have a series of data structures that stores information about what thumbnail to use, positioning, etc, etc, and then handle the rendering of each thumbnail required.

Of course, you would only render what you need, by checking the paint event args in your control and rendering the thumbnails that are in view and that require rendering.

Sherwoodsherwynd answered 22/1, 2009 at 21:32 Comment(3)
That will get a bit too complex for what I need it for. Adding the controls is not so much of a problem really. Any ideas how to solve (1) ?Cottontail
There is a global cap on the number of window handles your application can have. Each user control generates at least one handle (more if you have other controls inside) and your app will crash if you exceed the allowable number of handles.Nordrheinwestfalen
There is a limit of about 10K handles the OS will allow so, like in my case where I have a browser with potentially 200K-300K icons in a browser app, pagination is the only option.Myatt
C
2

Aha! I found something.

When the UserControl is not in view and it receives a Paint event, then e.ClipRectangle.IsEmpty is true!

Cottontail answered 22/1, 2009 at 22:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.