ASP.NET:滚动到控件

时间:2009-04-14 02:04:36

标签: asp.net controls scroll focus

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

9 个答案:

答案 0 :(得分:7)

Page.MaintainScrollPositionOnPostBack = False
Page.SetFocus(txtManagerName)

答案 1 :(得分: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.ClientScript.RegisterClientScriptBlock())不推荐使用Page.RegisterClientScriptBlock()。

答案 2 :(得分:5)

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

如果是这样,ASP.NET renders some javascript to automatically scroll to the top of the page可能会覆盖客户端验证的自动行为,以集中最后一个无效控件。

另外,您是否关闭了客户端验证?

如果您查看客户端验证生成的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,但这可能被上面讨论的其他机制之一覆盖。

答案 3 :(得分:2)

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

<%@ Page MaintainScrollPositionOnPostback="true" %>

答案 4 :(得分:2)

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

答案 5 :(得分:1)

你确定Focus()不会做你所描述的吗?在幕后,它基本上是在做“JavaScript解决方法” - 它将一些JS写入页面,该页面使用匹配的ID在控件上调用focus():

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

<script type="text/javascript">
//<![CDATA[
WebForm_AutoFocus('txtFocus2');//]]>
</script>

答案 6 :(得分:0)

您应该查看jQuery和ScrollTo插件

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

答案 7 :(得分:0)

我使用基本的HTML fragments取得了类似的成就。您只需保留一个具有已知ID的元素:

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

然后通过脚本,在服务器端打开更改URL:

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

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

答案 8 :(得分: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(),确保该按钮的CauseValidation = true。

你有它。