By default, when an UpdatePanel is refreshed upon postbacks, the navigation position of the page will not change because the postback is only a partial postback. It is a nice behavior in most cases, but in some cases, it can be very annoying. For instance, if you have a Wizard control defined in an UpdatePanel for user data entry, and if the form is very long, then you will need to scroll to the bottom of the page to click “Next” button to go to the next step. However, you will find that since the navigation position is “remembered”, in the second step you will have to manually scroll the page to the top to enter more data. Ideally, the navigation position should go to the top of the page in the second step to reduce the frustration of the user. This can be implemented by injecting some JavaScript code in your page. ShaneHenderson wrote an article on how to scroll to the top a page when clicking on only the Pager Controls in DataView, it works very well and can be modified for other controls as well. However, the limitation of the article is that it is static and you will have to know the rendered control ID in the HTML page source in order to use it. How can we make it more dynamic so that we can determine which control will cause the navigation position to scroll to the top, and which control will keep the navigation position upon the UpdatePanel postbacks.
Here is the JavaScript code provided in shenderson’s article:
<script type="text/javascript" language="javascript"> var postbackElement; Sys.WebForms.PageRequestManager.getInstance().add_beginRequest(beginRequest); Sys.WebForms.PageRequestManager.getInstance().add_pageLoaded(pageLoaded) function beginRequest(sender, args) { postbackElement = args.get_postBackElement(); } function pageLoaded(sender, args) { if (typeof(postbackElement) === "undefined") { return; } if ((postbackElement.id) === "ctl00_C1_JobsGridView") { window.scrollTo(0,0); } } </script>
If we take a deep look at the above code snippet, we will find that if we can, somehow, pass in the control’s ID to the second “If” statement, then we should be able to make the above code dynamic and shouldn’t have to worry about the rendered control ID.
With this in mind, we can add a HiddenField in the UpdatePanel to store the ID of the control interested in, then let the JavaScript code load the ID when needed.
<asp:HiddenField ID="hdnPostbackControlID" runat="server" Value="0" />
Then modify the above JavaScript code snippet as follows:
var postbackElement; Sys.WebForms.PageRequestManager.getInstance().add_pageLoaded(pageLoaded); Sys.WebForms.PageRequestManager.getInstance().add_beginRequest(beginRequest); function beginRequest(sender, args) { postbackElement = args.get_postBackElement(); } function pageLoaded(sender, args) { if (typeof(postbackElement) === "undefined") { return; } var id = document.getElementById('<%=hdnPostbackControlID.ClientID %>').value; /* Here we pass in the control's ID */ if ((postbackElement.id) === id) { window.scrollTo(0,0); } }
Finally, in code behind, when we need to enable a control to cause the navigation position to go to the top of the page upon postback, then we add this line to store the control’s ID:
Me.hdnPostbackControlID.Value = Me.btnSave.ClientID.ToString()
This way, other server controls on the page will not change the navigation position upon postback except the one specified in the above line.
Hope this will help and also appreciate your comment and feedback on this.