ページに特に大きなフォームがあります。フォームが検証され、フィールドが無効な場合、ウィンドウをそのコントロールまでスクロールしたいと考えています。コントロールの Focus() を呼び出しても、これは行われないようです。ウィンドウをコントロールまでスクロールする JavaScript の回避策を見つけましたが、ASP.NET に組み込まれているものはありますか?
9 に答える
Page.MaintainScrollPositionOnPostBack = False
Page.SetFocus(txtManagerName)
SO 問題は、WebControls ではなく HtmlGenericControls に集中しようとしていたためだと思います。
私は次のことに基づいて回避策を実行しました:
http://ryanfarley.com/blog/archive/2004/12/21/1325.aspx http://www.codeproject.com/KB/aspnet/ViewControl.aspx
...時間の都合上。
public static void ScrollTo(this HtmlGenericControl control)
{
control.Page.RegisterClientScriptBlock("ScrollTo", string.Format(@"
<script type='text/javascript'>
$(document).ready(function() {{
var element = document.getElementById('{0}');
element.scrollIntoView();
element.focus();
}});
</script>
", control.ClientID));
}
使用法:
if (!this.PropertyForm.Validate())
{
this.PropertyForm.ErrorMessage.ScrollTo();
failed = true;
}
(Page.RegisterClientScriptBlock() は Page.ClientScript.RegisterClientScriptBlock() に対して非推奨になっているように見えますが)。
ページで検証サマリーを使用していますか?
その場合、ASP.NETはいくつかの JavaScript をレンダリングして、ページの上部に自動的にスクロールします。これにより、クライアント側の検証の自動動作がオーバーライドされ、最後の無効なコントロールにフォーカスする可能性があります。
また、クライアント側の検証をオフにしましたか?
クライアント側の検証によって生成された JavaScript を見ると、次のようなメソッドが表示されます。
function ValidatorValidate(val, validationGroup, event) {
val.isvalid = true;
if ((typeof(val.enabled) == "undefined" || val.enabled != false) &&
IsValidationGroupMatch(val, validationGroup)) {
if (typeof(val.evaluationfunction) == "function") {
val.isvalid = val.evaluationfunction(val);
if (!val.isvalid && Page_InvalidControlToBeFocused == null &&
typeof(val.focusOnError) == "string" && val.focusOnError == "t") {
ValidatorSetFocus(val, event);
}
}
}
ValidatorUpdateDisplay(val);
}
ValidatorSetFocus への呼び出しに注意してください。これは、(最終的に) 次の行を使用して、問題のコントロールにフォーカスを設定しようとする、または複数のエラーがある場合は検証された最後のコントロールにフォーカスを設定しようとするかなり長いメソッドです。
if (typeof(ctrl.focus) != "undefined" && ctrl.focus != null) {
ctrl.focus();
Page_InvalidControlToBeFocused = ctrl;
}
この動作を機能させるには、理想的には、すべてのバリデーターがクライアント側に設定されていることを確認する必要があります-サーバー側のバリデーターは明らかにポストバックを必要とし、それは物事に影響を与える可能性があります(つまり、フォーカス/位置を失う)-そしてMaintainScrollPositionOnPostBackを設定しますtrue に設定すると、無効なフォーム要素ではなく、ページが送信ボタンにリロードされる可能性があります。
サーバー側の .Focus メソッドを使用すると、ASP.NET は "ページの読み込み時" (つまり、ページの下部近く) にいくつかの JavaScript をレンダリングしますが、これは上記で説明した他のメカニズムのいずれかによってオーバーライドされる可能性があります。
非常に簡単な解決策は、RequiredFieldValidator (または使用しているバリデータ コントロール) の SetFocusOnError プロパティを true に設定することです。
MaintainScrollPositionOnPostback の追加は、ASP.NET に組み込まれている最も近いものですが、必ずしも無効なフィールドにジャンプするとは限りません。
<%@ Page MaintainScrollPositionOnPostback="true" %>
Focus()があなたが説明していることをしないと確信していますか? 内部的には、基本的に「JavaScript の回避策」を実行しています。一致する ID を持つコントロールで focus() を呼び出すページに JS を書き込みます。
ページが処理を終了する前に、Focus() が最後に呼び出されたコントロールは、これをページに書き込みます。
<script type="text/javascript">
//<![CDATA[
WebForm_AutoFocus('txtFocus2');//]]>
</script>
基本的なHTML フラグメントを使用して同様のことを達成しました。既知の ID を持つ要素をそのままにしておくだけです。
<span id="CONTROL-ID"></span>
そして、スクリプトを介して、サーバー側で URL を変更します。
window.location += "#CONTROL-ID";
最初のケースでは、ページはリロードされず、コントロールまでスクロール ダウンするだけです。
jQuery と ScrollTo プラグインを調べる必要があります
次の Javascript を貼り付けます。
function ScrollToFirstError() {
Page_ClientValidate();
if (Page_IsValid == false) {
var topMostValidator;
var lastOffsetTop;
for (var i = 0; i < Page_Validators.length; i++) {
var vld = Page_Validators[i];
if (vld.isvalid == false) {
if (PageOffset(vld) < lastOffsetTop || lastOffsetTop == undefined) {
topMostValidator = vld;
lastOffsetTop = vld.offsetTop;
}
}
}
topMostValidator.scrollIntoView();
}
return Page_IsValid;
}
function PageOffset(theElement) {
var selectedPosY = 0;
while (theElement != null) {
selectedPosY += theElement.offsetTop;
theElement = theElement.offsetParent;
}
return selectedPosY;
}
次に、保存中のボタンの OnClientClick で ScrollToFirstError() を呼び出し、ボタンにも CausesValidation=true があることを確認します。
そこにあります。