0

この問題について何か助けていただければ幸いです。SO と Google を探してこの問題の解決策を探しましたが、100% 機能するものは見つかりませんでした。これが私の問題です(ページのセットアップ方法の説明についてはご容赦ください):

マスター ページに含まれるページがあります。このページは、UpdatePanel 内にある AjaxControlToolkit TabContainer を使用します。各 TabPanel は異なるユーザー コントロールをロードし、各ユーザー コントロールには、ユーザーがコントロール内でデータを追加/編集するかどうかに基づいて表示される 1:M 入力フォームを含めることができます。この機能はすべてうまく機能しますが、これらのフォームがビューポート内で見えなくなることがあります。

ユーザーが行うスクロールの量を最小限に抑えるために、PageRequestManager を使用して jQuery animate イベント ハンドラーを実装しました。基本的に私がやっていることは、ShowForm サーバー側メソッドを呼び出して、JavaScript をビルドし、endRequest でページに挿入することです。サーバー側のコードは次のとおりです。

private void ShowForm(bool pShowForm) {
    fsAdd.Visible = pShowForm;

    if (pShowForm) {
        LoadScript(FocusOnFormScript("control_client_id"), "control_client_id");
    }
}

protected void DropDownList_OnSelectedIndexChanged(object sender, EventArgs e) {
    //SelectedIndexChanged processing.
    MaintainFocusOnControl(KeepFocusOnFormScript("control_client_id"), "control_client_id");
}

private void LoadScript(string pScript, string pControlId) {
    ScriptManager.RegisterStartupScript(this.Page, this.Page.GetType(), "focusControl_" + pControlId, pScript, true);
}

private void MaintainFocusOnControl(string pScript, string pControlId) {
    ScriptManager.RegisterStartupScript(this.Page, this.Page.GetType(), "maintainFocus_" + pControlId, pScript, true);
}

/// <summary>
/// Scrolls to the form when it is made visible
/// </summary>
/// <param name="pControlId">The ClientID of the control to focus on after the form is made visible</param>
/// <returns></returns>
private string FocusOnFormScript(string pControlId) {
    string script = @"
    function FocusOnForm() {
        var offset = $('#" + pControlId + @"').offset();
        $('html, body').animate({ 
            scrollTop: offset.top+200,
            scrollLeft: offset.left+200}, 
            'slow', 
            'easeOutQuart'
        );
        /* This removes the event from the PageRequestManager immediately after the desired functionality is completed so that multiple events are not added */
        prm.remove_endRequest(FocusOnFormCaller);
    }
    prm.add_endRequest(FocusOnFormCaller);
    function FocusOnFormCaller(sender, args) {
        if (args.get_error() == undefined) {
            FocusOnForm();
        }
    }";
    return script;
}

/// <summary>
/// Scrolls to the form when it is made visible
/// </summary>
/// <param name="pControlId">The ClientID of the control to focus on after the form is made visible</param>
/// <returns></returns>
private string KeepFocusOnFormScript(string pControlId) {
    string script = @"
    function KeepFocusOnForm() {
        var offset = $('#" + pControlId + @"').offset();
        window.scrollTo(offset.left+500, offset.top+500); //just jump to the position; scrolling not needed

        /* This removes the event from the PageRequestManager immediately after the desired functionality is completed so that multiple events are not added */
        prm.remove_endRequest(KeepFocusOnFormCaller);
    }
    prm.add_endRequest(KeepFocusOnFormCaller);
    function KeepFocusOnFormCaller(sender, args) {
        if (args.get_error() == undefined) {
            KeepFocusOnForm();
        }
    }";
    return script;
}

このコードは 99% の確率でうまく機能します。1% の問題は、DropDownList のカスケードが必要な特定のフォームで発生します。DropDownList1 を選択すると、DropDownList2 は正しく読み込まれますが、ページのスクロール位置が失われ、DropDownList2 のビューがビューポートの一番下に移動します (今説明しているフォームの下に別のリストとフォームがあります)。

私は多くのことを試しました:

  • さまざまなMaintainScrollPositionOnPostBack設定
  • PageRequestManager._scrollPosition = null
  • scrollTopbeginRequestに格納し、 endRequestに設定する
  • 別の endRequestで window.scrollTo(xPos,yPos)を使用する
  • document.documentElement.scrollTop=yPos の使用
  • jQuery の .scrollTop(yPos)

私が奇妙だと思うのは、window.scrollTo または document.documentElement.scrollTop を呼び出す手動リンクを設定すると、それが機能することです。既に登録されている jQuery animate イベント ハンドラーを使用することもできますが、UpdatePanel の更新後にページが一番上にスクロールしてから、再び下にスクロールします。アニメーション コードを window.scrollTo または document.documentElement.scrollTop に置き換えると、機能しません。

4

1 に答える 1