Сброс положения прокрутки после асинхронной обратной передачи - ASP.NET

Каков наилучший способ восстановить положение прокрутки в верхней части страницы после асинхронной обратной передачи?

Асинхронная обратная передача инициируется из столбца ASP.NET GridView CommandField, а метод обновления панели обновления ASP.NET вызывается в GridView OnRowCommand.

Моим текущим приложением является веб-сайт ASP.NET 3.5.

РЕДАКТИРОВАТЬ: я получил отличные отзывы от всех, и я прекратил использовать метод PageRequestManager в теге сценария, но мой следующий вопрос:

Как мне настроить его выполнение только тогда, когда пользователь нажимает ASP.NET CommandField в моем элементе управления GridView? У меня есть другие кнопки на странице, которые выполняют асинхронную обратную передачу, которую я не хочу прокручивать в верхнюю часть страницы.

РЕДАКТИРОВАТЬ 1: Я разработал решение, где мне не нужно использовать PageRequestManager. Смотрите мой ответ для решения.

8 ответов

Решение

Вот следующее решение, которое я разработал на основе этого источника

ASP.NET Webform

<script language="javascript" type="text/javascript">
   function SetScrollEvent() {
      window.scrollTo(0,0);
   }
</script> 

<asp:GridView id="MyGridView" runat="server" OnRowDataBound="MyGridView_OnRowDataBound">
    <Columns>
        <asp:CommandField ButtonType="Link" ShowEditButton="true" />
    </Columns>
</asp:GridView>

ASP.NET Webform код позади

protected void MyGridView_OnRowDataBound(object sender, GridViewRowEventArgs e)
{
    if(e.Row.RowType.Equals(DataControlRowType.DataRow))
    {
        foreach (DataControlFieldCell cell in e.Row.Cells)
        {
            foreach(Control control in cell.Controls)
            {
                LinkButton lb = control as LinkButton;

                if (lb != null && lb.CommandName == "Edit")
                    lb.Attributes.Add("onclick", "SetScrollEvent();");
            }
        }
    }
}

Когда вы используете UpdatePanels, вам нужно подключиться к ASP.NET AJAX PageRequestManager.

Вам нужно будет добавить метод к перехватчикам событий endRequest:

Возникает после завершения асинхронной обратной передачи и возврата управления браузеру.

Так что у вас будет что-то вроде:

<script type="text/javascript">
  Sys.WebForms.PageRequestManager.getInstance().add_endRequest(pageLoaded);

  function pageLoaded(sender, args) {
     window.scrollTo(0,0);
  }
</script>

Что заставит браузер прокручивать обратно вверх страницы после завершения запроса на обновление.

Есть и другие события, которые вы можете подключить вместо:

beginRequest // Raised before the request is sent
initializeRequest // Raised as the request is initialised (good for cancelling)
pageLoaded // Raised once the request has returned, and content is loaded
pageLoading // Raised once the request has returned, and before content is loaded

Прелесть асинхронных постбэков в том, что страница будет поддерживать высоту прокрутки без необходимости устанавливать MaintainScrollPosition, так как не происходит "полной перезагрузки страницы", в этом случае вы действительно хотите, чтобы этот эффект имел место, поэтому вам нужно будет создайте его вручную.

Изменить, чтобы ответить на обновленный вопрос

Итак, если вам нужно сбросить положение только при определенных нажатиях кнопок, вам нужно сделать что-то вроде этого:

Начните с подключения к BeginRequest вместо этого, а также:

Sys.WebForms.PageRequestManager.getInstance().add_beginRequest(BeginRequestHandler);

Это потому, что в параметре args вы получаете доступ к:

args.get_postBackElement().id

Который сообщит вам идентификатор кнопки, которая запустила все событие - вы можете либо проверить значение здесь, и переместить страницу, либо сохранить ее в переменной, и запросить ее в конце запроса - зная о состоянии гонки, и т.д., когда пользователь нажимает другую кнопку, прежде чем ваше оригинальное обновление завершается.

Это должно привести вас к удаче - есть немало примеров по работе с событиями PageRequestManager.

Вот идеальное решение для сброса положения полосы прокрутки в ТОП в AJAX

Код на стороне клиента

function ResetScrollPosition()
{
    setTimeout("window.scrollTo(0,0)", 0);
}

Серверный код

ScriptManager.RegisterStartupScript(Page, this.GetType(), "ScrollPage", "ResetScrollPosition();", true);

Только window.scrollTo(0,0) не будет работать. В этом случае Ajax будет иметь приоритет, поэтому вы должны использовать функцию setTimeout.

Взяты из этого урока:

http://aspnet.4guysfromrolla.com/articles/111407-1.aspx

Мы устанавливаем MaintainScrollPositionOnPostback=true

Затем, если нам нужно сбросить позицию прокрутки, вызовите метод:

Private Sub ResetScrollPosition()
If Not ClientScript.IsClientScriptBlockRegistered(Me.GetType(), "CreateResetScrollPosition") Then
   'Create the ResetScrollPosition() function
   ClientScript.RegisterClientScriptBlock(Me.GetType(), "CreateResetScrollPosition", _
                    "function ResetScrollPosition() {" & vbCrLf & _
                    " var scrollX = document.getElementById('__SCROLLPOSITIONX');" & vbCrLf & _
                    " var scrollY = document.getElementById('__SCROLLPOSITIONY');" & vbCrLf & _
                    " if (scrollX && scrollY) {" & vbCrLf & _
                    "    scrollX.value = 0;" & vbCrLf & _
                    "    scrollY.value = 0;" & vbCrLf & _
                    " }" & vbCrLf & _
                    "}", True)

   'Add the call to the ResetScrollPosition() function
   ClientScript.RegisterStartupScript(Me.GetType(), "CallResetScrollPosition", "ResetScrollPosition();", True)
End If
End Sub 

Вы используете asp.net AJAX? Если это так, то в клиентских библиотеках есть два очень полезных события beginRequest и endRequest, одна из проблем с частичными / асинхронными обратными вызовами, заключается в том, что общая страница не имеет понятия о том, что вы делаете. события begin и endrequest позволят вам поддерживать позицию прокрутки на клиенте, у вас может быть переменная в js, которая установлена ​​на позицию прокрутки в beginrequest, а затем при запросе конца вы можете сбросить тот элемент scrollTop, который вам необходим. Конечно, я видел это сделано раньше, но не могу найти ссылку. плохо пост, если я найду пример

Page.RegisterStartupScript("MyScript", "<script language=javascript>setTimeout('window.scrollTo(0,0)', 0);</script>");

Поместите вышеупомянутое в функцию, которую вы хотите сказать, чтобы перейти к началу страницы. Например, когда страница недействительна, имейте ее там, и она добавит временный javascript, чтобы выстрелить вам в верхнюю часть страницы.

Вы установили свойство страницы MaintainScrollPosition? Не уверен, если это будет иначе, если вы делаете асинхронную обратную передачу или нет.

Изменить: Одна вещь, которую вы могли бы попытаться, это установить фокус на конкретный элемент в верхней части вашей страницы, что может помочь и может быть грязной работой вокруг.

Я использую скрытый ввод с именем hScrollTop, который я установил перед отправкой формы asp.net. Затем, когда страница загружается, она устанавливает scrollTop в соответствии со значением скрытого ввода.

Попробуйте этот код на новой странице.

<div style="height:500px"></div>

<form id="Form1" runat=server onsubmit="javascript:saveScrollTop();">
    <input type=submit value="Submit" runat=server>
    <input type="hidden" id="hScrollTop" runat=server>
</form>

<div style="height:1000px"></div>

<script language="javascript">
    function saveScrollTop() {
        document.getElementById("<%= hScrollTop.ClientID %>").value = document.body.scrollTop;
        return true;
    }

    window.onload = function() {
        document.body.scrollTop = document.getElementById("<%= hScrollTop.ClientID %>").value;
    }

</script>
Другие вопросы по тегам