Search code examples
c#winformsscrollpanel

How to Programmatically Scroll a Panel


I have a System.Windows.Forms.Panel with some content.

I am trying to programmatically scroll the panel (vertically) either up or down.

I have tried setting the AutoScrollPosition property to a new Point on the panel but that doesn't seem to do it.

I have the AutoScroll property set to true.

I even tried to set the VerticalScroll.Value twice as suggested here, but that doesn't seem to work either.

This is what I am currently doing:

//I have tried passing both positive and negative values.
panel.AutoScrollPosition = new Point(5, 10);

The X and Y values on AutoScrollPosition remain 0 and 0.

Any help or direction on this would be greatly appreciated it.

Thanks in advance,

Marwan


Solution

  • Here is a solution. I guess you can scroll your Panel by arbitrary position using Win32 however there is a simple trick to help you achieve your requirement here:

    public void ScrollToBottom(Panel p){
      using (Control c = new Control() { Parent = p, Dock = DockStyle.Bottom })
         {
            p.ScrollControlIntoView(c);
            c.Parent = null;
         }
    }
    //use the code
    ScrollToBottom(yourPanel);
    

    Or use extension method for convenience:

    public static class PanelExtension {
       public static void ScrollToBottom(this Panel p){
          using (Control c = new Control() { Parent = p, Dock = DockStyle.Bottom })
          {
             p.ScrollControlIntoView(c);
             c.Parent = null;
          }
       }
    }
    //Use the code
    yourPanel.ScrollToBottom();
    

    UPDATE

    If you want to set the exact position, modifying the code above a little can help:

    //This can help you control the scrollbar with scrolling up and down.
    //The position is a little special.
    //Position for scrolling up should be negative.
    //Position for scrolling down should be positive
    public static class PanelExtension {
        public static void ScrollDown(this Panel p, int pos)
        {
            //pos passed in should be positive
            using (Control c = new Control() { Parent = p, Height = 1, Top = p.ClientSize.Height + pos })
            {
                p.ScrollControlIntoView(c);                
            }
        }
        public static void ScrollUp(this Panel p, int pos)
        {
            //pos passed in should be negative
            using (Control c = new Control() { Parent = p, Height = 1, Top = pos})
            {
                p.ScrollControlIntoView(c);                
            }
        }
    }
    //use the code, suppose you have 2 buttons, up and down to control the scrollbar instead of clicking directly on the scrollbar arrows.
    int i = 0;
    private void buttonUp_Click(object sender, EventArgs e)
    {
       if (i >= 0) i = -1;
       yourPanel.ScrollUp(i--);
    }
    private void buttonDown_Click(object sender, EventArgs e)
    {
       if (i < 0) i = 0;
       yourPanel.ScrollDown(i++);
    }
    

    Another solution you may want to use is using Panel.VerticalScroll.Value. However I think you need more research to make it work as you expect. Because I can see once changing the Value, the scrollbar position and control position don't sync well. Notice that Panel.VerticalScroll.Value should be between Panel.VerticalScroll.Minimum and Panel.VerticalScroll.Maximum.