Click here to Skip to main content
Licence CPOL
First Posted 8 Feb 2007
Views 130,270
Downloads 1,047
Bookmarked 54 times

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

By | 8 Feb 2007 | Article
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.

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:

/// <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:

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:

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)

About the Author

George Mamaladze

Software Developer

Germany Germany

Member

Follow on Twitter Follow on Twitter
Tweeter: @gmamaladze
Google+: gmamaladze
Blog: gmamaladze.wordpress.com

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board. (secure sign-in)
 
Search this forum  
 FAQ
    Noise  Layout  Per page   
  Refresh
QuestionHow can you modify this code to retain focus on F5 Refresh as well as postback? [modified] Pinmembersarndt9:49 22 Feb '12  
QuestionFor some reason it is not working.... using vb.net PinmemberMember 779716713:08 19 Jan '12  
GeneralMy vote of 5 PinmemberreSPAWNed860:24 8 Dec '11  
QuestionDoes Not work with repeater ! please help !! Pinmemberjashlubana10:21 7 Sep '11  
AnswerRe: Does Not work with repeater ! please help !! PinmemberAlexsander Antunes6:31 14 Nov '11  
QuestionCan't you simple set MaintainScrollPositionOnPostback to "true" ? PinmemberFedor Steeman2:45 29 Mar '11  
AnswerRe: Can't you simple set MaintainScrollPositionOnPostback to "true" ? Pinmemberjeff_wong16:19 7 Jul '11  
GeneralUse with Master Pages PinmemberRebecca Caudill5:04 21 Jan '10  
GeneralProblem when client id changes Pinmemberstesson22:31 10 May '09  
Generalvalue vs Value PinmemberRobinT771:20 21 Apr '09  
GeneralDoes not work with span's PinmemberRob van Rijen5:45 14 Jul '08  
GeneralI found a compilation error PinmemberMartin Neu4:20 5 Jun '08  
AnswerRe: I found a compilation error PinmemberMr MM7:19 23 Jun '08  
GeneralDetermining AJAX or NON-AJAX PinmemberMember 477649810:57 23 Apr '08  
I have plenty of pages that sometimes use AJAX and sometimes do normal postbacks and I needed to handle that issue.   I found that when using AJAX an extra header value is present, by checking that you can handle the 'either/or' of whether you are using AJAX or not.
I set a global variable in my page class...
   bool bUsingAjax = false;
 
and in Page_Load I set it...
      if (Request.Headers["x-microsoftajax"] != null)
         bUsingAjax = true;
 
Then if you need to swap between ClientScript or ScriptManager you can do a simple if(){}else{} based on your boolean.   This lets you handle either occurance just as easily.
 
Just thought I'd share. Shucks | :->
Generaldinamic controls or only in a few controls. [modified] PinmemberMember 41375966:03 10 Mar '08  
QuestionCan be use for FocusOnError() Pinmembermdsahni4:01 9 Mar '08  
GeneralUser Controls lost focus with ajax.net PinmemberRoni Peterson9:55 19 Dec '07  
GeneralMasterpages with Updatepanel (.Net 3.5) [modified] PinmemberDUMITRU Guraliuc23:06 11 Dec '07  
QuestionAjax Problem PinmemberSaad Alam4:53 31 Aug '07  
GeneralshowModalDialog Pinmemberjohndhunter5:46 23 May '07  
GeneralAbsurd behaviour is happening :S Pinmembergamzun6:20 22 May '07  
GeneralFirefox/IE inconsistencies Pinmemberbszom5:04 10 May '07  
QuestionRe: Firefox/IE inconsistencies PinmemberGeorge Mamaladze21:53 10 May '07  
AnswerRe: Firefox/IE inconsistencies Pinmemberbszom23:03 10 May '07  
Generaldynamic created usercontrols PinmemberVolleyknaller22:45 17 Apr '07  

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

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

Permalink | Advertise | Privacy | Mobile
Web04 | 2.5.120529.1 | Last Updated 9 Feb 2007
Article Copyright 2007 by George Mamaladze
Everything else Copyright © CodeProject, 1999-2012
Terms of Use
Layout: fixed | fluid