0

I have a list that it's populated with usercontrols (~300 usercontrols // every UC has a PictureBox and 10 Labels). I display all of them in a Flowlayoutpanel but when I scroll down or up it is very slow and kinda unresponsive. I'm already using a DoubleBuffered Flowlayoutpanel and that 'trick' with SuspendLayout and ResumeLayout. What I'm trying to do: I scroll down with mouse -> when the first two usercontrols are not in the view anymore, remove them -> add two new usercontrols from the list at the bottom. And that should work also in the opposite way: scroll up with mouse -> when the last two are not in the view anymore, remove them -> add two new usercontrols from the list at the top. Picture

I checked and tried everything that I found but it's not working... Some links that I checked:

 private void FlowLayoutPanel_MouseMove(object sender, MouseEventArgs e)
        {
            // move flowlayoutpanel with mouse
            if (e.Button != MouseButtons.Left)
                return;

            Point pointDifference = new Point(Cursor.Position.X + mouseDownPoint.X, Cursor.Position.Y - mouseDownPoint.Y);
            if ((mouseDownPoint.X == Cursor.Position.X) && (mouseDownPoint.Y == Cursor.Position.Y))
                return;

            Point currAutoScroll = FlowLayoutPanel.AutoScrollPosition;
            FlowLayoutPanel.AutoScrollPosition = new Point(Math.Abs(currAutoScroll.X) - pointDifference.X, Math.Abs(currAutoScroll.Y) - pointDifference.Y);
            mouseDownPoint = Cursor.Position;

            
            //
            Point locationOnForm = UClist[0].FindForm().PointToClient(
            UClist[0].Parent.PointToScreen(new Point(UClist[0].Location.X,UClist[0].Location.Y+300)));
            if (locationOnForm.Y < 190)
            {
                FlowLayoutPanel.SuspendLayout();
                FlowLayoutPanel.Controls.Clear();
                FlowLayoutPanel.Controls.AddRange(UClist.Skip(2).Take(2).ToArray());
                FlowLayoutPanel.ResumeLayout();
            }   
        }

How should I do?

EDIT This is what I was talking 'bout Pic

Dani99
  • 11
  • 2
  • IMO, among those links, the only one you should consider is TaW's answer: [Fake-scrolling containers with very many controls](https://stackoverflow.com/a/39810717/7444103). It's also (probably) the only one where this: `FlowLayoutPanel.Controls.Clear();` doesn't hurt your app's feelings (note that `.Controls.Clear()` doesn't *remove* the Controls, it just removes the references from the parent Container, so you cannot see them anymore, but those Controls - and their content - are still all there). – Jimi Oct 14 '20 at 15:15
  • 1
    What *causes harm* are the Images you want to show: those 1000 images you'll load, one per UC, will be decompressed in memory. Each non compressed Image will take, say, 3 megabytes (a 1MB compressed image can be actually 3 to 10 times larger in memory - probably more than that), so you'll load 3GB of Images, plus all the rest. So you'll have to cache those Images and also load/dispose of the Images when the FLP is scrolled. Fortunately, TaW has already writen almost everything you need, you just need to add the caching part. – Jimi Oct 14 '20 at 15:15
  • Thank you for your answer, @Jimi! But from TaW's answer I don't understand this: float pageSize = flowLayoutPanel2.ClientSize.Height / (uc1.Height + uc1.Margin.Top + uc1.Margin.Bottom); vScrollBar1.Maximum = (int)( 1f * theUCs.Count / (pageSize)) + 9; – Dani99 Oct 14 '20 at 15:57
  • I don't know how to set (and where) the Maximum value of the VScrollBar. I tried putting the UClist.Count to the vScrollBar1.Maximum after I finished populating the list but that does not work... – Dani99 Oct 14 '20 at 15:59
  • You may want to move that code to a method that will set a new maximum value each time you modify the `List`: when you add to or remove from list one or more controls, call that method, pass the references of your `FlowLayoutPanel` container and the ScrollBar control and the size of the UC (assuming your UCs all have the same size, otherwise you'll probably have to show them *boxed* [like this](https://stackoverflow.com/a/54565075/7444103)). The method can then perform that calculation and assign the `Maximum` value to the ScrollBar. – Jimi Oct 14 '20 at 17:00
  • _I checked and tried everything that I found but it's not working_ Hm, you may have gotten things wrong. We can't know what you did.. – TaW Oct 14 '20 at 18:32
  • I got it working with the vScrollBar like in TaW's answear :D! But it's weird though because the last 10~20 usercontrols aren't shown properly (i'll upload a pic). I'll check that later. Now... how can I do the same thing inside the MouseMove function I posted above (because I need the flowlayoutpanel to be scrolling with mouse)? – Dani99 Oct 14 '20 at 21:42
  • Also make sure that the Image you're displaying inside your UserControl PictureBox is an appropriate size for the control (should be very small based on your description and details). Loading a high res image and then letting the "Zoom" SizeMode take care of re-sizing is another common problem in these types of apps. – Idle_Mind Oct 14 '20 at 22:19
  • Thank you for your answer, @Idle_Mind! I already did that and didn't work... I just make the flowlayoutpanel bigger and that did the trick. Does it matter if the size of the Flowlayoutpanel it's not the same with the vScrollBar? How much should I put for SmallChange and LargeChange because sometimes I don't get all the usercontrols when scrolling and sometimes I get too much "blank page" (the flowlayoutpanel does not have usercontrols but I can scroll though). – Dani99 Oct 15 '20 at 19:36

0 Answers0