Click here to Skip to main content
15,890,882 members
Articles / Web Development / ASP.NET
Article

Maintain focus between postbacks in ASP.NET 2.0, also in ASP.NET AJAX

Rate me:
Please Sign up or sign in to vote.
4.87/5 (35 votes)
8 Feb 2007CPOL1 min read 285.7K   3.1K   57   57
A workaround to maintain focus between postbacks in ASP.NET 2.0, also in ASP.NET AJAX without SmartNavigation.

The Problem

Let's assume you have two TextBoxes. The first one has a TextChanged event attached and AutoPostBack set to true. When you edit TextBox1 and move to TextBox2, the control TextBox2 loses its focus.

Case 1: The normal postback in ASP.NET 2.0 without smart navigation.

The trick is to save the name of the control which received focus at last, and then restore it after postback. There is a hidden field __LASTFOCUS, and we are going to use it.

First of all, let us go through all "relevant" controls and set the attribute onfocus to save their name when they receive focus. "Relevant" are controls which potentially can receive focus. Because we do not want to set this attribute to each control explicitly, we just define types of "relevant" controls and enumerate them recursively.

C#
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);
}

Add aditional control types in the first if condition under the function private void HookOnFocus(Control CurrentControl).

Now, we need to set focus after the postback. Insert the following JavaScript as a constant in your page:

C#
/// <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) {}
    }";

and this statement to Page_Load:

C#
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);
}

Case 2: A "tiny Postback" inside the UpdatePanel in ASP.NET 2.0 AJAX

The only difference is that setting the focus must happen after each update inside UpdatePanel. In this case, the script registered using Page.ClientScript.RegisterStartupScript() will execute only after each global postback. We need to use ScriptManager.RegisterStartupScript() instead. The Page_Load will look like this:

C#
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);
}

Links

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer
Germany Germany
Tweeter: @gmamaladze
Google+: gmamaladze
Blog: gmamaladze.wordpress.com

Comments and Discussions

 
GeneralRe: Cursor at the end? Pin
efeigenb8-Oct-07 4:55
efeigenb8-Oct-07 4:55 
GeneralRe: Cursor at the end? Pin
George Mamaladze8-Oct-07 5:06
George Mamaladze8-Oct-07 5:06 
GeneralA variation Pin
Kidomezode22-Mar-07 0:23
Kidomezode22-Mar-07 0:23 
GeneralRe: A variation Pin
George Mamaladze22-Mar-07 5:02
George Mamaladze22-Mar-07 5:02 
QuestionSet Focus Pin
kristien van dijck1-Mar-07 0:22
kristien van dijck1-Mar-07 0:22 
QuestionAnother One... Pin
User 299712415-Feb-07 17:15
User 299712415-Feb-07 17:15 
AnswerRe: Another One... Pin
George Mamaladze15-Feb-07 21:28
George Mamaladze15-Feb-07 21:28 
GeneralRe: Another One... Pin
User 299712419-Feb-07 15:32
User 299712419-Feb-07 15:32 
Thanks..for your help..

I dont' believe that such many programmer in Microsoft couldn't think like you!!..

ajax and focus form is really important!!

You are better than any other programmer in Microsoft, i think.

Here is the Result.

You said.

1. Palce ScriptManager as a first control on the MasterPage
2. Place an UpdatePanel on each child page.
3. Place controls in UpdatePanels and set apropriate properties and events.
4. Include following code in MasterPage:

So, I placed ScriptManager as a first control("below the form tag"-any other location causes error. Blush | :O ) on the MasterPage.

and then, Place an UPdatePanel on my child page.
and then, do the number 3.

Number 4, Include following code in MasterPage.

There was a error, But I found how to fix that.

private const string SCRIPT_DOFOCUS =
      @"window.setTimeout('DoFocus()', 1);
        function DoFocus()
        {
            try {
                document.getElementById('REQUEST_LASTFOCUS').focus();
            } catch (ex) {}
        }";


above part should be resides "master page" and "child page" both.
Because, without child page there was a error.

And, I thought Light-Weight Master. (less code, you know, not every page require textbox. Yet Inserting Main Script to Master Page is some kind useful.) So, I inserted all code to Child Page.

It works!!

Thanks...Thanks..Thanks..

Thank you for helping me.

Have a ni~~~~~ce day~!
QuestionYour Script is Brilliant!! Really Thanks.. [modified] Pin
User 299712415-Feb-07 14:37
User 299712415-Feb-07 14:37 
AnswerRe: Your Script is Brilliant!! Really Thanks.. Pin
George Mamaladze15-Feb-07 20:42
George Mamaladze15-Feb-07 20:42 
GeneralRe: Your Script is Brilliant!! Really Thanks.. Pin
User 299712419-Feb-07 14:33
User 299712419-Feb-07 14:33 
QuestionMaintain focus between postbacks Pin
Ulf Andersson11-Feb-07 23:11
Ulf Andersson11-Feb-07 23:11 
AnswerRe: Maintain focus between postbacks Pin
George Mamaladze11-Feb-07 23:56
George Mamaladze11-Feb-07 23:56 
AnswerRe: Maintain focus between postbacks Pin
Ulf Andersson12-Feb-07 0:39
Ulf Andersson12-Feb-07 0:39 
GeneralRe: Maintain focus between postbacks Pin
George Mamaladze12-Feb-07 1:19
George Mamaladze12-Feb-07 1:19 
QuestionScroll position Pin
robrich9-Feb-07 4:27
robrich9-Feb-07 4:27 
AnswerRe: Scroll position Pin
George Mamaladze10-Feb-07 9:29
George Mamaladze10-Feb-07 9:29 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.