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 t
I had an issue where I couldnt get my panel to scroll back to top . I tried many things to try and get the panel to scroll back to the top after populating it with many controls.
Nomatter what I did it always put the VScroll bar to the bottom.
After exhaustive testing I found it was because my controls had the TabStop property set to true (default on user controls) was causing the issue.
Setting TabStop to false fixed it.
Create an control that sits slightly outside the visible area (so -1 at the top and clientsize+1 ) and then call ScrollControlIntoView:
public static class PanelExtension {
public static void ScrollDown(this Panel p)
{
using (Control c = new Control() { Parent = p, Height = 1, Top = p.ClientSize.Height + 1 })
{
p.ScrollControlIntoView(c);
}
}
public static void ScrollUp(this Panel p )
{
using (Control c = new Control() { Parent = p, Height = 1, Top = -1})
{
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.
private void buttonUp_Click(object sender, EventArgs e)
{
yourPanel.ScrollUp();
}
private void buttonDown_Click(object sender, EventArgs e)
{
yourPanel.ScrollDown();
}
with yourpanel.SetAutoScrollMargin(1, 1); you can set very fine scrolling steps and then take a timer to call the srolling when buttons are down
This surprisingly works! NOTE THE MINUS SIGN in the code. There is strange behavior in setting scroll position. If you set the position to exact value (50), it goes negative when you read it next time (-50). So you have to invert it before setting new scroll value.
Scroll down:
private void ButtonScrollDown_OnClick(object sender, EventArgs e)
{
Point current = yourScrollPanel.AutoScrollPosition;
Point scrolled = new Point(current.X, -current.Y + 10);
yourScrollPanel.AutoScrollPosition = scrolled;
}
Scroll up similarly, (-current.Y - 10)
Use @King King Answered Code and if you want to hide horizontal and vertical scroll bar, just apply the below code in the constructor or initialization.
yourPanel.AutoScroll = false;
yourPanel.HorizontalScroll.Maximum = 0;
yourPanel.HorizontalScroll.Visible = false;
yourPanel.VerticalScroll.Maximum = 0;
yourPanel.VerticalScroll.Visible = false;
yourPanel.AutoScroll = true;
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();
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
.
If you have a class that derives from Panel
, then call these two protected methods to scroll the panel:
// The bottom is off screen; scroll down. These coordinates must be negative or zero.
SetDisplayRectLocation(0, AutoScrollPosition.Y - item.BoundingRect.Bottom + ClientRectangle.Bottom);
AdjustFormScrollbars(true);
In my example, item.BoundingRect.Bottom
is the Y coordinate of the bottom of a thumbnail, and I need to scroll the panel down so that the whole thumbnail is visible.
@King King's solution of creating a temporary Control just so that scrolling could be done seemed "heavy" to me. And @Hans Passant's suggestion of setting AutoScrollMinSize
and AutoScrollPosition
didn't work for me.
Leave AutoScroll
to its default value of 'true'.