我在一个页面中有一个特别大的表格。当表单经过验证并且字段无效时,我想将窗口滚动到该控件。调用控件的 Focus() 似乎没有这样做。我找到了一种 JavaScript 解决方法来将窗口滚动到控件,但是 ASP.NET 中有内置的东西吗?
9 回答
Page.MaintainScrollPositionOnPostBack = False
Page.SetFocus(txtManagerName)
您是否在页面上使用验证摘要?
如果是这样,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,但这可能会被上面讨论的其他机制之一覆盖。
所以我相信问题是因为我试图专注于 HtmlGenericControls 而不是 WebControls。
我刚刚结束了基于以下的解决方法:
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() 弃用)。
添加 MaintainScrollPositionOnPostback 是最接近 ASP.NET 内置的,但不一定会跳转到无效字段。
<%@ Page MaintainScrollPositionOnPostback="true" %>
非常简单的解决方案是将RequiredFieldValidator(或您正在使用的任何验证器控件)的SetFocusOnError 属性设置为true
您确定Focus()不会做您所描述的事情吗?在底层,它本质上是在做“JavaScript 变通办法”——它将一些 JS 写入页面,该页面调用具有匹配 ID 的控件上的 focus():
在页面完成处理之前最后调用 Focus() 的任何控件都将其写入页面:
<script type="text/javascript">
//<![CDATA[
WebForm_AutoFocus('txtFocus2');//]]>
</script>
你应该看看 jQuery 和 ScrollTo 插件
我已经使用基本的HTML 片段实现了类似的功能。您只需留下一个具有已知 ID 的元素:
<span id="CONTROL-ID"></span>
然后通过脚本,在服务器端更改 url:
window.location += "#CONTROL-ID";
在第一种情况下,页面不会重新加载,它只会向下滚动到控件。
粘贴以下 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。
你有它。