Scroll 2 panels at the same time

2019-06-25 09:47发布

问题:

I have windows forms (.net 2.0) control that contains a splicontainer inside. Splitcontainer, as usually, contains 2 panels (standard thing). The Autoscroll is set to true.

I've been struggling for quite a time to achieve something like synchronizing those two panels, so scrolling one of these will scroll the second one also. I achieved it - using Scroll event (not a problem).

However, this event is not called when we're tabbing through controls on the one of the panels (e.g. textboxes) - not really like what it's on the msdn.microsoft.com/en-us/library/system.windows.forms.scrollablecontrol.scroll.aspx ("The Scroll event occurs when the user scrolls through the client area by interacting with the scroll bars, or when the user navigates between controls and the active control scrolls into view. ".

So, in fact, the panels are not really synchronized :|

I'm aware of the fact, that giving focus to not visible control contained in a scrollable control calls it's ScrollToControl(Control) event which "makes" the new control(textbox) visible. To give more details, I can say that both panels are identical (size and controls).

How would you achieve what I'm looking for?

回答1:

Here is exactly what you need to scroll 2 panels in a SplitContainer. This will scroll even if you are tabbing to controls not in the current view.


this.splitContainer1.Panel1.Paint += new System.Windows.Forms.PaintEventHandler(PanelPaint);
this.splitContainer1.Panel2.Paint += new System.Windows.Forms.PaintEventHandler(PanelPaint);

Point mPrevPan1Pos = new Point();
Point mPrevPan2Pos = new Point();

void PanelPaint(object sender, System.Windows.Forms.PaintEventArgs e)
{
   if (splitContainer1.Panel1.AutoScrollPosition != mPrevPan1Pos)
   {
      splitContainer1.Panel2.AutoScrollPosition = new System.Drawing.Point(-splitContainer1.Panel1.AutoScrollPosition.X, -splitContainer1.Panel1.AutoScrollPosition.Y);
      mPrevPan1Pos = splitContainer1.Panel1.AutoScrollPosition;
   }
   else if (splitContainer1.Panel2.AutoScrollPosition != mPrevPan2Pos)
   {
      splitContainer1.Panel1.AutoScrollPosition = new System.Drawing.Point(-splitContainer1.Panel2.AutoScrollPosition.X, -splitContainer1.Panel2.AutoScrollPosition.Y);
      mPrevPan2Pos = splitContainer1.Panel2.AutoScrollPosition;
   }
}


回答2:

I took the answer from @SwDevMan81 and rounded it out with the last piece I needed to get it work in VS 2012, .Net 4.5.

Part 1 is inside my form class:

    #region Synchronize the scrolling of the two panels in the SplitContainer.

    private Point _prevPan1Pos = new Point();
    private Point _prevPan2Pos = new Point();

    void PanelPaint(object sender, System.Windows.Forms.PaintEventArgs e)
    {
        SynchronizeSplitContainerScrollbars();
    }

    private void SynchronizeSplitContainerScrollbars()
    {
        if (splitContainer1.Panel1.AutoScrollPosition != _prevPan1Pos)
        {
            splitContainer1.Panel2.AutoScrollPosition = new System.Drawing.Point(-splitContainer1.Panel1.AutoScrollPosition.X, -splitContainer1.Panel1.AutoScrollPosition.Y);
            _prevPan1Pos = splitContainer1.Panel1.AutoScrollPosition;
        }
        else if (splitContainer1.Panel2.AutoScrollPosition != _prevPan2Pos)
        {
            splitContainer1.Panel1.AutoScrollPosition = new System.Drawing.Point(-splitContainer1.Panel2.AutoScrollPosition.X, -splitContainer1.Panel2.AutoScrollPosition.Y);
            _prevPan2Pos = splitContainer1.Panel2.AutoScrollPosition;
        } 
    }

    #endregion

Part 2 is in the constructor for the Form. I had to add events for the Scroll events themselves.

        // Setup so we can synchronize the scrolling of the two panels in the SplitContainer.
        splitContainer1.Panel1.Paint += PanelPaint;
        splitContainer1.Panel2.Paint += PanelPaint;
        splitContainer1.Panel1.Scroll += (obj, scrollEventArgs) => SynchronizeSplitContainerScrollbars();
        splitContainer1.Panel2.Scroll += (obj, scrollEventArgs) => SynchronizeSplitContainerScrollbars();


回答3:

Why don't you place the split container completely in a scrolling thingy instead of putting the scrollbar thingies inside the split container? That way they naturally share the same scrollbar and the split container can be as wide as necessary to fit the entire form.