C# UserControl.VerticalScroll.Value not being set

2019-02-24 06:57发布

问题:

I've got a chunk of C# code that is supposed to set VerticalScroll.Value within a class that inherits from UserControl. It gets called when any child object of the class changes sizes. The class has its AutoScroll property set to true.

    public void ScrollTo(int top)
    {
        if (top >= this.VerticalScroll.Minimum && top <= this.VerticalScroll.Maximum)
        {
            this.VerticalScroll.Value = top;
        }
    }

The problem is, when tracing through the code, sometimes this.VerticalScroll.Value gets set, sometimes it keeps the value that it had before this method was called.

Is this a bug in VS, or are there known conditions under which the value will ignore attempts to set it?

Thanks, Rob

回答1:

I was having the same problem and came upon the solution in some dev forum. After setting the VerticalScroll.Value, you have to call PerformLayout() to make the scrolling control update. So do this:

scrollingcontrol.VerticalScroll.Value = top;
scrollingcontrol.PerformLayout();

This makes more sense than setting .Value twice, though it seems to have the same effect.



回答2:

I was running into the same problem, and I found a solution on the MSDN webpage (won't let me post links, 'cause I'm a new user).

The suggested solution was to assign to .Value twice, and it worked for me:

int newVerticalScrollValue = 
         pDashboard.VerticalScroll.Value - pDashboard.VerticalScroll.SmallChange;

pDashboard.VerticalScroll.Value = newVerticalScrollValue;
pDashboard.VerticalScroll.Value = newVerticalScrollValue;


回答3:

FlowLayoutPanel seems to be a different beast. The scroll bar does move down, but the value of flowlayoutpanel.VerticalScroll.Value remains at 0. I tried all above techniques plus some DoEvents() and Thread.Sleep(), even a timer which fully yielded before doing its next iteration. It all failed. I eventually discovered that DisplayRectangle.Y was instantly expressing the scroll change...

private void PrintButton_Click(object sender, EventArgs e)
{
    FlowLayoutPanel flp = TheBuildFlowLayoutPanel;
    List<Bitmap> printPics = new List<Bitmap>();
    int printLastY = 100;
    flp.VerticalScroll.Value = 0;
    while (flp.DisplayRectangle.Y < printLastY) // DisplayRect.Y becomes successively more negative
    {
        Bitmap bmp = new Bitmap(flp.Width, flp.Bounds.Height);
        printPics.Add(bmp);
        flp.DrawToBitmap(bmp, flp.ClientRectangle);
        printLastY = flp.DisplayRectangle.Y;
        flp.VerticalScroll.Value = Math.Min(flp.VerticalScroll.Maximum, flp.VerticalScroll.Value + flp.Height);
    }

    flp.VerticalScroll.Value = 0;
    for (int i = 0; i < printPics.Count; i++)
    {
        printPics[i].Save("C:\\Temp" + i.ToString() + ".bmp");
    }
}


回答4:

In my case it was necessary to set the VerticalScroll.Value to a different value and then to the value of interest, e.g.

this.panel1.VerticalScroll.Value = verticalScrollPosition - 1;
this.panel1.VerticalScroll.Value = verticalScrollPosition;   

Take care that the scroll position is always between VerticalScroll.Minimum and VerticalScroll.Maximum.