65.9K
CodeProject 正在变化。 阅读更多。
Home

在 ASP.NET 2.0 和 ASP.NET AJAX 中保持回传之间的焦点

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.87/5 (33投票s)

2007年2月9日

CPOL

1分钟阅读

viewsIcon

294052

downloadIcon

3131

在 ASP.NET 2.0 和 ASP.NET AJAX 中保持回传之间的焦点,没有使用 SmartNavigation 的解决方法。

问题

假设您有两个 TextBox。第一个有一个附加的 TextChanged 事件,并且 AutoPostBack 设置为 true。 当您编辑 TextBox1 并移动到 TextBox2 时,控件 TextBox2 会失去焦点。

情况 1: ASP.NET 2.0 中没有智能导航的正常回传。

诀窍是保存最后获得焦点的控件的名称,然后在回传后恢复它。 存在一个隐藏字段 __LASTFOCUS,我们将使用它。

首先,让我们遍历所有“相关”控件,并设置 onfocus 属性以在它们获得焦点时保存它们的名称。“相关”是指可能获得焦点的控件。 由于我们不想将此属性显式地设置为每个控件,我们只需定义“相关”控件的类型并递归枚举它们。

protected void Page_Load(object sender, EventArgs e)
{
     //sets onfocus event to all apropriate controls on the page.

     if (!IsPostBack)
          HookOnFocus(this.Page as Control);
}
/// <summary>

/// This function goes recursively all child controls and sets 

/// onfocus attribute if the control has one of defined types.

/// </summary>

/// <param name="CurrentControl">the control to hook.</param>

private void HookOnFocus(Control CurrentControl)
{
    //checks if control is one of TextBox, DropDownList, ListBox or Button

    if ((CurrentControl is TextBox) ||
        (CurrentControl is DropDownList) ||
        (CurrentControl is ListBox) ||
        (CurrentControl is Button))
    //adds a script which saves active control on receiving focus 

    //in the hidden field __LASTFOCUS.

        (CurrentControl as WebControl).Attributes.Add(
           "onfocus",
           "try{document.getElementById('__LASTFOCUS').value=this.id} 
               catch(e) {}");
        //checks if the control has children

        if (CurrentControl.HasControls())
            //if yes do them all recursively

            foreach (Control CurrentChildControl in CurrentControl.Controls)
                HookOnFocus(CurrentChildControl);
}

在函数 private void HookOnFocus(Control CurrentControl) 下的第一个 if 条件中添加额外的控件类型。

现在,我们需要在回传后设置焦点。 将以下 JavaScript 插入到您的页面中作为常量

/// <summary>

/// This script sets a focus to the control with a name to which

/// REQUEST_LASTFOCUS was replaced. Setting focus heppens after the page

/// (or update panel) was rendered. To delay setting focus the function

/// window.setTimeout() will be used.

/// </summary>

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)
{
    //sets onfocus event to all apropriate controls on the page.

    if (!IsPostBack)
        HookOnFocus(this.Page as Control);

    //replaces REQUEST_LASTFOCUS in SCRIPT_DOFOCUS with 

    //the posted value from Request    

    //["__LASTFOCUS"]

    //and registers the script to start after the page was rendered

    Page.ClientScript.RegisterStartupScript(
        typeof(MyPage),
        "ScriptDoFocus",
        SCRIPT_DOFOCUS.Replace("REQUEST_LASTFOCUS", 
                               Request["__LASTFOCUS"]),
        true);
}

情况 2:ASP.NET 2.0 AJAX 中 UpdatePanel 内部的“微型回传”

唯一的区别是必须在 UpdatePanel 内部的每次更新后设置焦点。 在这种情况下,使用 Page.ClientScript.RegisterStartupScript() 注册的脚本仅在每次全局回传后执行。 我们需要使用 ScriptManager.RegisterStartupScript() 替代。 Page_Load 看起来像这样

protected void Page_Load(object sender, EventArgs e)
{
    //sets onfocus event to all apropriate controls on the page.

    if (!IsPostBack)
            HookOnFocus(this.Page as Control);

    //replaces REQUEST_LASTFOCUS in SCRIPT_DOFOCUS with the posted value from 

    //Request ["__LASTFOCUS"]

    //and registers the script to start after Update panel was rendered

    ScriptManager.RegisterStartupScript(
        this,
        typeof(MyPage),
        "ScriptDoFocus",
        SCRIPT_DOFOCUS.Replace("REQUEST_LASTFOCUS", Request["__LASTFOCUS"]),
        true);
}

链接

© . All rights reserved.