9

我在一个页面中有一个特别大的表格。当表单经过验证并且字段无效时,我想将窗口滚动到该控件。调用控件的 Focus() 似乎没有这样做。我找到了一种 JavaScript 解决方法来将窗口滚动到控件,但是 ASP.NET 中有内置的东西吗?

4

9 回答 9

8
Page.MaintainScrollPositionOnPostBack = False
Page.SetFocus(txtManagerName)
于 2012-09-20T19:31:46.200 回答
5

您是否在页面上使用验证摘要?

如果是这样,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,但这可能会被上面讨论的其他机制之一覆盖。

于 2009-04-15T00:00:18.933 回答
5

所以我相信问题是因为我试图专注于 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() 弃用)。

于 2009-04-14T23:59:23.633 回答
2

添加 MaintainScrollPositionOnPostback 是最接近 ASP.NET 内置的,但不一定会跳转到无效字段。

<%@ Page MaintainScrollPositionOnPostback="true" %>
于 2009-04-14T02:08:01.180 回答
2

非常简单的解决方案是将RequiredFieldValidator(或您正在使用的任何验证器控件)的SetFocusOnError 属性设置为true

于 2010-06-01T10:35:41.547 回答
1

您确定Focus()不会做您所描述的事情吗?在底层,它本质上是在做“JavaScript 变通办法”——它将一些 JS 写入页面,该页面调用具有匹配 ID 的控件上的 focus():

在页面完成处理之前最后调用 Focus() 的任何控件都将其写入页面:

<script type="text/javascript">
//<![CDATA[
WebForm_AutoFocus('txtFocus2');//]]>
</script>
于 2009-04-14T02:08:23.097 回答
0

你应该看看 jQuery 和 ScrollTo 插件

http://demos.flesler.com/jquery/scrollTo/

于 2009-04-14T02:07:47.653 回答
0

我已经使用基本的HTML 片段实现了类似的功能。您只需留下一个具有已知 ID 的元素:

<span id="CONTROL-ID"></span>

然后通过脚本,在服务器端更改 url:

window.location += "#CONTROL-ID";

在第一种情况下,页面不会重新加载,它只会向下滚动到控件。

于 2009-04-14T23:39:37.330 回答
0

粘贴以下 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。

你有它。

于 2012-02-28T15:54:35.497 回答