?
Solved

VB.NET - Maintain scrollbar position on a panel

Posted on 2007-08-09
9
Medium Priority
?
821 Views
Last Modified: 2013-11-07
I have a panel on a page that has a horizontal scrollbar.  Inside the panel is a gridview that is 2600 pixels wide.  The gridview has sorting capability enabled.  I'm trying to figure out if there is any way to maintain the scrollbar position after the page posts back when a user sorts the grid.  There does not appear to be any inherent property for this, any thoughts?
0
Comment
Question by:stretch73
  • 5
  • 4
9 Comments
 
LVL 18

Expert Comment

by:DropZone
ID: 19663505
I do this for the page itself using JavaScript.  Although I haven't tried it for a single block element, I think it should work the same.

The idea is this:  You register event handlers for the onScroll, onClick, and onKeyPress (because all three could change the scrolling position) which will just take the current coordinates of the scrollable window and update hidden values on the form.  These values are posted back when the form is submitted.  On a post-back, you generate client-side script to auto-scroll the window back to the last coordinates set.

I set the following JavaScript on every page.  I have a control I created just to encapsulate this, but you should be able to call RegisterStartUpScript() from the Render() method of the control with the following javascript code:

<script language="javascript" type="text/javascript">
<!--
// _getFormElementByName
function _getFormElementByName(strFormName, strElementName) {
      for (var i = 0; i < document.forms[strFormName].elements.length; i++) {
            var frmElement = document.forms[strFormName].elements[i];
            if (frmElement.type == 'hidden' && frmElement.name == strElementName) {
                  return frmElement;
            }
      }
      return null;
}
// AutoScroller_GetCoords
function AutoScroller_GetCoords() {
      var scrollX, scrollY;
      var strFormName = '_ctl0';
      if (document.all) {
            if (!document.documentElement.scrollLeft)
                  scrollX = document.body.scrollLeft;
            else
                  scrollX = document.documentElement.scrollLeft;
            if (!document.documentElement.scrollTop)
                  scrollY = document.body.scrollTop;
            else
                  scrollY = document.documentElement.scrollTop;
      } else {
            scrollX = window.pageXOffset;
            scrollY = window.pageYOffset;
      }
      var frmScrollLeft = _getFormElementByName(strFormName, '__SCROLL_X');
      var frmScrollTop  = _getFormElementByName(strFormName, '__SCROLL_Y' );
      if (frmScrollLeft)
            frmScrollLeft.value = scrollX;
      if (frmScrollTop)
            frmScrollTop.value = scrollY;
}
// AutoScroller_Scroll
function AutoScroller_Scroll() {
      var x = 0;
      var y = 0;
      var strFormName = '_ctl0';
      var frmScrollLeft = _getFormElementByName(strFormName, '__SCROLL_X');
      var frmScrollTop  = _getFormElementByName(strFormName, '__SCROLL_Y' );
      if (frmScrollLeft != null) {x = frmScrollLeft.value;}
      if (frmScrollTop  != null) {y = frmScrollTop.value; }
      window.scrollTo(x, y);
}
// Initialize
window.onscroll   = AutoScroller_GetCoords;
window.onclick    = AutoScroller_GetCoords;
window.onkeypress = AutoScroller_GetCoords;

AutoScroller_Scroll();
// -->
</script>

Like I said, you'll need to modify the code to support your panel only, and not the entire page.

   -dZ.
0
 
LVL 18

Expert Comment

by:DropZone
ID: 19663538
I forgot to mention, that I register 2 hidden fields called "__SCROLL_X" and "__SCROLL_Y" using Page.RegisterHiddenField().  These are then accessed by the JavaScript.

The trick is to read these on PostBack and register them again for output.

    -dZ.
0
 
LVL 18

Expert Comment

by:DropZone
ID: 19663683
Here's an updated version of the script to scroll an element and not the page.  I haven't tested this, so I can't guarantee that it will work; it is just to give you an idea.

<script language="javascript" type="text/javascript">
<!--
// You should inject here the ClientIDs for:
var _PANEL_ELEMENT_ID_ = '';   // The panel
var _FORM_ELEMENT_ID_  = '';   // The form

// _getFormElementByName
function _getFormElementByName(strFormName, strElementName) {
      for (var i = 0; i < document.forms[strFormName].elements.length; i++) {
            var frmElement = document.forms[strFormName].elements[i];
            if (frmElement.type == 'hidden' && frmElement.name == strElementName) {
                  return frmElement;
            }
      }
      return null;
}

// AutoScroller_GetCoords
function AutoScroller_GetCoords() {
      var scrollX, scrollY;
      var strFormName  = '_ctl0';
      var panelElem = document.getElementById(_PANEL_ELEMENT_ID_);

      if (document.all && panelElem != null) {
            if (panelElem.scrollLeft != null)
                  scrollX = panelElem.scrollLeft;
            if (panelElem.scrollTop != null)
                  scrollY = panelElem.scrollTop;
      }
      var frmScrollLeft = _getFormElementByName(strFormName, '__SCROLL_X');
      var frmScrollTop  = _getFormElementByName(strFormName, '__SCROLL_Y' );
      if (frmScrollLeft != null)
            frmScrollLeft.value = scrollX;
      if (frmScrollTop != null)
            frmScrollTop.value = scrollY;
}
// AutoScroller_Scroll
function AutoScroller_Scroll() {
      var x = 0;
      var y = 0;
      var panelElem = document.getElementById(_PANEL_ELEMENT_ID_);

    if (panelElem != null) {
            var frmScrollLeft = _getFormElementByName(_FORM_ELEMENT_ID_, '__SCROLL_X');
            var frmScrollTop  = _getFormElementByName(_FORM_ELEMENT_ID_, '__SCROLL_Y' );
            if (frmScrollLeft != null) {x = frmScrollLeft.value;}
            if (frmScrollTop  != null) {y = frmScrollTop.value; }

            panelElem.scrollTo(x, y);
    }
}
// Initialize
window.onscroll   = AutoScroller_GetCoords;
window.onclick    = AutoScroller_GetCoords;
window.onkeypress = AutoScroller_GetCoords;

AutoScroller_Scroll();
// -->
</script>

     -dZ.
0
NEW Veeam Agent for Microsoft Windows

Backup and recover physical and cloud-based servers and workstations, as well as endpoint devices that belong to remote users. Avoid downtime and data loss quickly and easily for Windows-based physical or public cloud-based workloads!

 

Author Comment

by:stretch73
ID: 19664074
dZ,

Good stuff, going to take me a minute to modify this for a panel.  Looks good though.

N
0
 

Author Comment

by:stretch73
ID: 19664414
Can you give me any hint as to how to get the client IDs in there, nothing I'm trying is working.
0
 
LVL 18

Expert Comment

by:DropZone
ID: 19664898
First, don't just put that javascript into the page template; register it as a startup script by calling RegisterStartUpScript() from the OnPreRender() method of your page (or control).

Sub Control_OnPreRender(e As EventArgs)
Begin
    Dim strScript As StringBuilder
    Dim FormID As String

    strScript = new StringBuilder()
    strScript.Append("<script......")
    ' etc. etc. etc.

    ' inject the control's ClientID into the javascript
    strScript.Append("var _PANEL_ELEMENT_ID_ = '" & Me.ClientID  & "';")

    ' To get the Form's ID:
    For Each Ctrl In (Me.Page.Controls)
        If (Ctrl Is System.Web.UI.HtmlControls.HtmlForm) Then


    Next

    FormID =
    strScript.Append("var _FORM_ELEMENT_ID_  = '" &  & "';")  

    Me.Page.RegisterStartupScript('ScrollPanel', strScript.ToString)
End
0
 

Author Comment

by:stretch73
ID: 19664913
There isn't a Render method for the panel control.  There is a pre-render though.
0
 

Author Comment

by:stretch73
ID: 19664928
Ignore the last comment, I sent it before I saw your latest.
0
 
LVL 18

Accepted Solution

by:
DropZone earned 750 total points
ID: 19664937
SORRY FOR THE DOUBLE POST, but I hit TAB+ENTER by mistake and got posted before I was finished. Below is the real post:


First, don't just put that javascript into the page template; register it as a startup script by calling RegisterStartUpScript() from the OnPreRender() method of your page (or control).

Sub Control_OnPreRender(e As EventArgs)
Begin
    Dim strScript As StringBuilder
    Dim FormID As String
    Dim Ctrl As Control

    strScript = new StringBuilder()
    strScript.Append("<script......")
    ' etc. etc. etc.

    ' inject the control's ClientID into the javascript
    strScript.Append("var _PANEL_ELEMENT_ID_ = '" & Me.ClientID  & "';")

    ' To get the Form's ID:
    For Each Ctrl In (Me.Page.Controls)
        If (Ctrl Is System.Web.UI.HtmlControls.HtmlForm) Then
            FormID = (Ctrl As HtmlForm).ClientID
            Exit For
        End If
    Next

    Ctrl = Nothing

    strScript.Append("var _FORM_ELEMENT_ID_  = '" & FormID & "';")  
    ' etc. etc. etc.

    Me.Page.RegisterStartupScript('ScrollPanel', strScript.ToString)

    strScript = Nothing
End
0

Featured Post

Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Today I had a very interesting conundrum that had to get solved quickly. Needless to say, it wasn't resolved quickly because when we needed it we were very rushed, but as soon as the conference call was over and I took a step back I saw the correct …
If you need to start windows update installation remotely or as a scheduled task you will find this very helpful.
Exchange organizations may use the Journaling Agent of the Transport Service to archive messages going through Exchange. However, if the Transport Service is integrated with some email content management application (such as an anti-spam), the admin…
We’ve all felt that sense of false security before—locking down external access to a database or component and feeling like we’ve done all we need to do to secure company data. But that feeling is fleeting. Attacks these days can happen in many w…
Suggested Courses
Course of the Month14 days, 13 hours left to enroll

839 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question