如何防止Focus()方法将页面滚动到顶部

6
我有一组文本框在网格视图中,我使用Focus()方法来恢复焦点到目标文本框。问题是:

当页面可滚动时,在文本更改事件中调用Focus方法时,页面会跳转到顶部。这是一个令人困惑的行为。

我的问题是:

有没有办法防止Focus()方法使页面跳转到顶部?

我的代码:

protected void txt_evaluateWeights_TextChanged(object sender, EventArgs e)
        {

            calc();
            int index = ((System.Web.UI.WebControls.GridViewRow)(((RadTextBox)sender).Parent.NamingContainer)).DataItemIndex;

            ((RadTextBox)gv_Evaluation.Rows[index + 1].Cells[3].FindControl("txt_evaluateWeights")).Focus();//Here is the problem. 
        }

注意:

  • 我使用了asp:TextBox,遇到了同样的问题。

  • 我的网格视图在更新面板中。


编辑:

Javascript解决方法:

var lastFocusedControlId = "";

function focusHandler(e) {
    document.activeElement = e.originalTarget;
}

function appInit() {
    if (typeof (window.addEventListener) !== "undefined") {
        window.addEventListener("focus", focusHandler, true);
    }
    Sys.WebForms.PageRequestManager.getInstance().add_pageLoading(pageLoadingHandler);
    Sys.WebForms.PageRequestManager.getInstance().add_pageLoaded(pageLoadedHandler);
}

function pageLoadingHandler(sender, args) {
    lastFocusedControlId = typeof (document.activeElement) === "undefined"
        ? "" : document.activeElement.id;
}

function focusControl(targetControl) {
    if (Sys.Browser.agent === Sys.Browser.InternetExplorer) {
        var focusTarget = targetControl;
        if (focusTarget && (typeof (focusTarget.contentEditable) !== "undefined")) {
            oldContentEditableSetting = focusTarget.contentEditable;
            focusTarget.contentEditable = false;
        }
        else {
            focusTarget = null;
        }
        try {
            targetControl.focus();
            if (focusTarget) {
                focusTarget.contentEditable = oldContentEditableSetting;
            }
        }
        catch (err) { }
    }
    else {
        targetControl.focus();
    }

}

function pageLoadedHandler(sender, args) {
    if (typeof (lastFocusedControlId) !== "undefined" && lastFocusedControlId != "") {
        var newFocused = $get(lastFocusedControlId);
        if (newFocused) {
            focusControl(newFocused);
        }
    }
}

Sys.Application.add_init(appInit);
6个回答

4

如果您正在使用更新面板和jQuery,那么解决方案就非常简单。假设您的文本框ID为tbDeliveryCost。不要使用tbDeliveryCost.Focus(),而是使用以下代码:

string script = string.Format("$('#{0}').focus();", tbDeliveryCost.ClientID);
ScriptManager.RegisterStartupScript(this, this.GetType(), "SetFocus", script, true);

4
与其试图修复Focus方法的行为,还有一个替代方案。我没有尝试过,但这个页面讨论了这个问题,并使用一些客户端JavaScript来记住哪个控件拥有焦点,然后在UpdatePanel刷新后将焦点放回该对象。请务必阅读评论以获取脚本更新信息。
如果您使用此方法,则应从代码后台中删除对Focus的调用,并让此脚本在客户端处理它。

非常感谢您提供这个绝妙的解决方案。我已经编辑了我的问题,您是否建议对这段代码进行任何改进? - Anyname Donotcare
1
目前我没有发现任何问题(实际上还没有使用过)。所以如果在不同的浏览器中它能正常工作,那么我建议你不要去动它。 - patmortech
但是在JavaScript中,===是什么意思? - Anyname Donotcare
2
不是笔误。这意味着它会检查两个值是否相同,而且它们的类型也相同。所以,例如,1=="1" 是 true,但 1==="1" 是 false。 - patmortech

1

您可以尝试使用 maintainScrollPositionOnPostBack 选项:

<%@ Page MaintainScrollPositionOnPostback="true" %> 

1
你可以使用这个jQuery插件来滚动到你的文本框:
$(...).scrollTo( $('<%= txt_evaluateWeights.ClientID %>') )

1

在设置焦点后,您可以尝试这个。

Response.Write("<script type='text/javascript'>$(...).scollTo( $('<%= txt_evaluateWeights.ClientID %>') )
</script>");

1

这个问题已经被问了zillion

这是ASP.NET JS库中的一个错误,解决方法很麻烦:

var oldScroll = window.scrollTo;
window.scrollTo = function(){};

//... the ugly ASP.NET stuff

window.scrollTo = oldScroll;

彻底的解决方案是停止使用Microsoft ASP.NET,开始使用一种更好的技术允许您编写客户端脚本。


嗯,你认为asp.net不是一种好的技术吗?!! - Anyname Donotcare
这绝对不值得花钱。=) - thwd
但是我知道的是 SOF 是使用这种技术构建的。 - Anyname Donotcare
1
我仍然不会向任何人推荐它。 - thwd
2
值得一提的是,Stack Overflow是使用ASP.NET MVC构建的,这与使用带有UpdatePanels的WebForms完全不同。 - patmortech

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接