VB.NET - Maintain scrollbar position on a panel

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?
stretch73Asked:
Who is Participating?
 
DropZoneConnect With a Mentor Commented:
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
 
DropZoneCommented:
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
 
DropZoneCommented:
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
Cloud Class® Course: Microsoft Office 2010

This course will introduce you to the interfaces and features of Microsoft Office 2010 Word, Excel, PowerPoint, Outlook, and Access. You will learn about the features that are shared between all products in the Office suite, as well as the new features that are product specific.

 
DropZoneCommented:
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
 
stretch73Author Commented:
dZ,

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

N
0
 
stretch73Author Commented:
Can you give me any hint as to how to get the client IDs in there, nothing I'm trying is working.
0
 
DropZoneCommented:
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
 
stretch73Author Commented:
There isn't a Render method for the panel control.  There is a pre-render though.
0
 
stretch73Author Commented:
Ignore the last comment, I sent it before I saw your latest.
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.