この問題について何か助けていただければ幸いです。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
- scrollTopをbeginRequestに格納し、 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 に置き換えると、機能しません。