在ASP.NET开发中,控件焦点的管理是一个常见问题。当用户从一个文本框切换到另一个文本框时,如果页面发生PostBack,那么当前控件可能会失去焦点。本文将介绍如何通过编程方式管理页面上的焦点,确保用户体验的流畅性。
在ASP.NET 2.0中,如果不使用智能导航,可以通过保存最后一个获得焦点的控件名称,并在PostBack后恢复它来解决这个问题。可以使用一个隐藏字段__LASTFOCUS
来实现这一功能。
首先,需要为页面上所有可能获得焦点的控件设置onfocus
事件,以便在它们获得焦点时保存它们的名称。称这些控件为“相关”控件。为了避免显式设置每个控件的这个属性,可以定义“相关”控件的类型,然后递归地枚举它们。
以下是C#代码示例:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
HookOnFocus(this.Page as Control);
}
}
private void HookOnFocus(Control CurrentControl)
{
if ((CurrentControl is TextBox) ||
(CurrentControl is DropDownList) ||
(CurrentControl is ListBox) ||
(CurrentControl is Button))
{
(CurrentControl as WebControl).Attributes.Add("onfocus", "try{document.getElementById('__LASTFOCUS').value=this.id} catch(e) {}");
if (CurrentControl.HasControls())
{
foreach (Control CurrentChildControl in CurrentControl.Controls)
{
HookOnFocus(CurrentChildControl);
}
}
}
}
接下来,需要在PostBack后设置焦点。将以下JavaScript代码作为页面中的常量插入:
private const string SCRIPT_DOFOCUS =
@"
window.setTimeout('DoFocus()', 1);
function DoFocus()
{
try {
document.getElementById('REQUEST_LASTFOCUS').focus();
} catch (ex) {}
}
";
并在Page_Load
方法中添加以下语句:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
HookOnFocus(this.Page as Control);
string scriptDoFocus = SCRIPT_DOFOCUS.Replace("REQUEST_LASTFOCUS", Request["__LASTFOCUS"]);
Page.ClientScript.RegisterStartupScript(typeof(MyPage), "ScriptDoFocus", scriptDoFocus, true);
}
}
这样,当页面PostBack后,焦点将被设置到之前获得焦点的控件上。
在ASP.NET2.0 AJAX中,如果使用UpdatePanel进行“微小的PostBack”,设置焦点的逻辑需要稍作调整。在这种情况下,焦点设置必须在UpdatePanel更新后进行。
与普通PostBack不同,不能使用Page.ClientScript.RegisterStartupScript()
来注册脚本,而应该使用ScriptManager.RegisterStartupScript()
。
以下是C#代码示例:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
HookOnFocus(this.Page as Control);
string scriptDoFocus = SCRIPT_DOFOCUS.Replace("REQUEST_LASTFOCUS", Request["__LASTFOCUS"]);
ScriptManager.RegisterStartupScript(this, typeof(MyPage), "ScriptDoFocus", scriptDoFocus, true);
}
}