web-dev-qa-db-fra.com

Comment faire défiler un panneau par programme

J'ai un System.Windows.Forms.Panel avec du contenu.

J'essaie de faire défiler le panneau par programme (verticalement) vers le haut ou le bas.

J'ai essayé de définir la propriété AutoScrollPosition sur une nouvelle Point sur le panneau, mais cela ne semble pas le faire.

La propriété AutoScroll est définie sur true.

J'ai même essayé de définir le VerticalScroll.Value deux fois comme suggéré ici , mais cela ne semble pas fonctionner non plus.

C'est ce que je suis en train de faire:

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

Les valeurs X et Y sur AutoScrollPosition restent 0 et 0.

Toute aide ou direction à ce sujet serait grandement appréciée.

Merci d'avance,

Marwan

Voici une solution. Je suppose que vous pouvez faire défiler votre Panel par position arbitraire à l'aide de Win32, mais il existe un truc simple pour vous aider à atteindre vos objectifs ici:

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);

Ou utilisez la méthode d'extension pour plus de commodité:

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();

METTRE À JOUR

Si vous voulez définir la position exacte, modifier légèrement le code ci-dessus peut aider:

//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++);
}

Une autre solution que vous pouvez utiliser est d'utiliser Panel.VerticalScroll.Value. Cependant, je pense que vous avez besoin de plus de recherche pour que cela fonctionne comme vous le souhaitez. Comme je peux voir une fois que l'on change la variable Value, la position de la barre de défilement et celle du contrôle ne sont pas bien synchronisées. Notez que Panel.VerticalScroll.Value doit être compris entre Panel.VerticalScroll.Minimum et Panel.VerticalScroll.Maximum.

13
King King

Essaye ça:- panel.ScrollControlIntoView (childcontrol);

Cela devrait marcher. childcontrol est le contrôle particulier que vous souhaitez afficher dans votre zone d'affichage.

3
Sagnik Majumder

Si vous avez une classe dérivée de Panel, appelez ces deux méthodes protégées pour faire défiler le panneau:

// 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);

Dans mon exemple, item.BoundingRect.Bottom est la coordonnée Y du bas d'une vignette et je dois faire défiler le panneau vers le bas pour que la vignette entière soit visible.

La solution de @ King King consistant à créer un contrôle temporaire juste pour que le défilement puisse être fait me paraissait "lourde". Et la suggestion de @Hans Passant de régler AutoScrollMinSize et AutoScrollPosition n'a pas fonctionné pour moi.

Laissez AutoScroll à sa valeur par défaut de 'true'.

2
Ron

Cela fonctionne étonnamment! Notez le signe moins dans le code. Il y a un comportement étrange dans la définition de la position du défilement. Si vous définissez la position sur la valeur exacte (50), elle devient négative à la prochaine lecture (-50). Vous devez donc l’inverser avant de définir une nouvelle valeur de défilement. 

Défiler vers le bas:

private void ButtonScrollDown_OnClick(object sender, EventArgs e)
{
    Point current = yourScrollPanel.AutoScrollPosition;
    Point scrolled = new Point(current.X, -current.Y + 10);
    yourScrollPanel.AutoScrollPosition = scrolled;
}

Défilement similaire, (-current.Y - 10)

1
Milan Švec

Utilisez @King King Answered Code et si vous souhaitez masquer les barres de défilement horizontale et verticale, appliquez simplement le code ci-dessous dans le constructeur ou l’initialisation.

        yourPanel.AutoScroll = false;
        yourPanel.HorizontalScroll.Maximum = 0;
        yourPanel.HorizontalScroll.Visible = false;
        yourPanel.VerticalScroll.Maximum = 0;
        yourPanel.VerticalScroll.Visible = false;
        yourPanel.AutoScroll = true;
1
suneel ranga

J'ai eu un problème qui empêchait le panneau de défiler de nouveau au début. J'ai essayé beaucoup de choses pour que le panneau revienne au début après l'avoir rempli avec de nombreux contrôles. 

Nomatter a toujours mis la barre VScroll au fond des choses.

Après des tests exhaustifs, j’ai trouvé que c’était parce que la propriété TabStop était définie sur true (valeur par défaut sur les contrôles utilisateur) qui était à l’origine du problème. 

Définir TabStop sur false l'a corrigé.

1