Click here to Skip to main content
16,004,761 members
Articles / Web Development / ASP.NET
Article

Automatically set control focus after ASP.NET AutoPostBack

Rate me:
Please Sign up or sign in to vote.
2.33/5 (5 votes)
28 Jun 20052 min read 162.1K   1.2K   46   20
Automatically set control focus after ASP.NET AutoPostBack.

Introduction

Wouldn't it be nice if ASP.NET managed setting the focus of web controls after autopostback? This article will show you a fairly effortless way of achieving this.

The Solution

  1. Download the source code above and compile it.
  2. Include the built assembly as a reference on your ASP.NET solution.
  3. In your ASP.NET code-behind file, you will see a line that looks like this:
    C#
    public class WebForm1 : System.Web.UI.Page
    {
    

    Change this to:

    C#
    public class WebForm1 : WebControls.Page
    {
    
  4. Test your ASP.NET solution. You'll find that when your controls auto-postback, they now set focus back to themselves when the page is reloaded.

How does this work?

The way the code works is that it inherits the System.Web.UI.Page class and overrides two key methods:

  • OnInit()
  • OnPreRender()

When the page is initialized, it searches recursively for any controls that are of a specific type (see code below). If it finds these controls, it adds the event handler that is called during autopostback. When the event is fired, it sets the focus control to the event sender.

During the pre-render, if a control has been set to get focus on load, then JavaScript is written to the client to automatically set focus to the control.

The new Page class also has a mechanism for setting focus at any time during its life-cycle. (For e.g., on Page_Load, a default control may be given the initial focus.)

C#
public class Page : System.Web.UI.Page 
{
    internal System.Web.UI.WebControls.WebControl setFocusControl = null;

    private void LoadControlEvents(System.Web.UI.ControlCollection controls)
    {
        foreach (System.Web.UI.Control control in controls)
        {
            if (control.Controls != null)
                LoadControlEvents(control.Controls);

            if (control is TextBox)
            {
                ((TextBox)control).TextChanged += 
                       new EventHandler(Control_Event);
            }
            else if (control is Button)
            {
                ((Button)control).Click += new EventHandler(Control_Event);
            }
            else if (control is LinkButton)
            {
                ((LinkButton)control).Click += 
                        new EventHandler(Control_Event);
            }
            else if (control is ImageButton)
            {
                ((ImageButton)control).Click += new 
                  System.Web.UI.ImageClickEventHandler(ImageButtonHandler);
            }
            else if (control is DropDownList)
            {
                ((DropDownList)control).SelectedIndexChanged += 
                               new EventHandler(Control_Event);
            }
            else if (control is ListBox)
            {
                ((ListBox)control).SelectedIndexChanged += 
                          new EventHandler(Control_Event);
            }
            else if (control is CheckBox)
            {
                ((CheckBox)control).CheckedChanged += 
                      new EventHandler(Control_Event);
            }
            else if (control is CheckBoxList)
            {
                //Not Tested
                ((CheckBoxList)control).SelectedIndexChanged += 
                               new EventHandler(Control_Event);
            }
            else if (control is RadioButton)
            {
                //Not Tested
                ((RadioButton)control).CheckedChanged += 
                        new EventHandler(Control_Event);
            }
            else if (control is RadioButtonList)
            {
                //Not Tested
                ((RadioButtonList)control).SelectedIndexChanged += 
                                  new EventHandler(Control_Event);
            }
            else if (control is Calendar)
            {
                //Not Tested
                ((Calendar)control).SelectionChanged += 
                       new EventHandler(Control_Event);
            }
        }
    }

    protected override void OnInit(EventArgs e)
    {
        LoadControlEvents(this.Controls);

        base.OnInit (e);
    }

    private void Control_Event(object sender, System.EventArgs e)
    {
        SetFocusControl(sender);
    }

    private void ImageButtonHandler(object sender, 
                      System.Web.UI.ImageClickEventArgs e)
    {
        SetFocusControl(sender);
    }

    private void SetFocusControl(object sender)
    {
        if ((setFocusControl == null) && 
                 (sender is System.Web.UI.WebControls.WebControl))
            setFocusControl = (System.Web.UI.WebControls.WebControl)sender;
    }

    public void SetFocus(System.Web.UI.WebControls.WebControl control)
    {
        setFocusControl = control;
    }

    protected override void OnPreRender(EventArgs e)
    {
        base.OnPreRender (e);

        //Setfocus script
        if ((setFocusControl != null) && 
                 (!this.IsStartupScriptRegistered("SetControlFocus")))
            this.RegisterStartupScript(
                "SetControlFocus", 
                string.Format("<script language="'\""JavaScript\"'>document" + 
                              ".getElementById('{0}').focus();</script>", 
                              setFocusControl.ClientID));
    }
}

Points to Consider

This same code should work with any page that has inherited from the base System.Web.UI.WebControls. The code above may also be modified to set focus to any custom control.

I have not tested this code in browsers other than IE 6.0 but I would imagine that any problems should be easily fixed with modifications to the generated JavaScript.

Please email me any enhancements that you make to this class and I will keep this article updated.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
Australia Australia
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralPerformance considerations Pin
Ben Lewies7-Sep-09 0:10
Ben Lewies7-Sep-09 0:10 
GeneralRe: Performance considerations Pin
MJSantosLx10-Mar-17 3:54
MJSantosLx10-Mar-17 3:54 
Generalthanks.. Pin
benyamin_202012-Jan-09 5:32
benyamin_202012-Jan-09 5:32 
GeneralProblem with datalist Edit mode Pin
ecsmoore8-Mar-08 23:50
ecsmoore8-Mar-08 23:50 
QuestionProblem with Ajax Enabled Web page Pin
CodeAli19-Sep-07 0:59
CodeAli19-Sep-07 0:59 
Generalmove focus to next element Pin
anarayan13-Apr-06 5:53
anarayan13-Apr-06 5:53 
GeneralRe: move focus to next element Pin
PeterB7226-Mar-07 3:34
PeterB7226-Mar-07 3:34 
NewsRe: move focus to next element Pin
Holger Schmid26-Apr-07 23:49
Holger Schmid26-Apr-07 23:49 
GeneralRe: move focus to next element Pin
Member 29997386-Dec-07 6:33
Member 29997386-Dec-07 6:33 
GeneralRe: move focus to next element Pin
Member 1021312615-Aug-13 23:48
Member 1021312615-Aug-13 23:48 
QuestionAdd Datalist and Datagrid controls Pin
viju874422-Nov-05 8:27
viju874422-Nov-05 8:27 
AnswerRe: Add Datalist and Datagrid controls Pin
Simon McEnlly22-Nov-05 22:48
Simon McEnlly22-Nov-05 22:48 
Questionhow to use in vb.net Pin
Jeff Kok10-Jul-05 2:06
Jeff Kok10-Jul-05 2:06 
AnswerRe: how to use in vb.net Pin
Simon McEnlly14-Jul-05 3:33
Simon McEnlly14-Jul-05 3:33 
GeneralSmartNavigation Pin
bryanallott5-Jul-05 23:27
bryanallott5-Jul-05 23:27 
GeneralRe: SmartNavigation Pin
Simon McEnlly6-Jul-05 3:15
Simon McEnlly6-Jul-05 3:15 
GeneralSomething different Pin
njappboy5-Jul-05 10:35
njappboy5-Jul-05 10:35 
GeneralRe: Something different [modified] Pin
Member 29997386-Dec-07 6:51
Member 29997386-Dec-07 6:51 
GeneralI think... a better version Pin
Durlabh29-Jun-05 2:04
Durlabh29-Jun-05 2:04 
Hi,

Whenever postback events are fired, we find the the control that caused the postback looses the focus. This is iritiating from user experience perspective. To resolve this issue this is what we deployed in one of our applications:

In every ASPX page we called a javascript function such as

<body onload='BodyOnLoad("tbDateFrom");'>


Here tbDateFrom is the name of the control on which we want to focus when first time page is loaded. The same function can be attached through server side script only but I chose to keep it client side so that I can change the default control name at my will. The javascript function BodyOnLoad was coded as:

function BodyOnLoad(defaultControl)<br />
<br />
{<br />
<br />
   // If postback then check whether we want to<br />
<br />
   // focus on an alternative control that had caused<br />
<br />
   // postback<br />
<br />
   if(IsPostBack && PostBackControl != undefined)<br />
<br />
      defaultControl = PostBackControl;<br />
<br />
   // Find the element and if it's not disabled<br />
<br />
         // set focus on the desired element<br />
<br />
   obj = document.getElementById(defaultControl);<br />
<br />
   if(obj != null && !obj.disabled)<br />
<br />
      obj.focus();<br />
<br />
}

As you can see above, we are using the method to achieve two functionalities. First, we identify the default element on which focus should be set when the form is loaded. At the same time, we also use the same method to focus on the control that caused the postback. Here's the necessary code that we included in our page to implement the postback-control identification functionality:

Friend DefaultFocusControl As Control<br />
<br />
Private Sub Page_PreRender(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.PreRender<br />
<br />
   ' If programmer didn't set the default focus in case of server error<br />
<br />
   ' check if we are in Postback mode. Try to set focus on the control<br />
<br />
   ' that caused postback<br />
<br />
   If DefaultFocusControl Is Nothing AndAlso IsPostBack Then<br />
<br />
      DefaultFocusControl = GetPostbackControl(Me)<br />
<br />
      ' If postback is through control bar such as on click of Add button<br />
<br />
      ' then it shouldn't remain on the button bar control<br />
<br />
      If TypeOf DefaultFocusControl Is LinkButton Then<br />
<br />
         ' Ignored some controls<br />
<br />
         If TypeOf DefaultFocusControl.Parent Is ControlBar OrElse TypeOf DefaultFocusControl.Parent Is MenuDock Then<br />
<br />
            DefaultFocusControl = Nothing<br />
<br />
         End If<br />
<br />
      End If<br />
<br />
End If<br />
<br />
If DefaultFocusControl Is Nothing Then<br />
<br />
   RegisterStartupScript("IsPostBackScript", " IsPostBack = true; ")<br />
<br />
Else<br />
<br />
   RegisterStartupScript("IsPostBackScript", " IsPostBack = true;PostBackControl='" & DefaultFocusControl.ClientID & "'; ")<br />
<br />
End If<br />
<br />
End Sub<br />
<br />
    Function GetPostbackControl(ByVal targPage As Page) As Control<br />
        If targPage.IsPostBack Then<br />
            ' try to find the name of the postback control in the hidden <br />
            ' __EVENTTARGET field <br />
            Dim ctlName As String = targPage.Request.Form("__EVENTTARGET")<br />
            ' if the string is not null, return the control with that name <br />
            If ctlName.Trim().Length > 0 Then<br />
                Return targPage.FindControl(ctlName)<br />
            End If<br />
            ' the trick above does not work if the postback is caused by standard <br />
            ' buttons. <br />
            ' In that case we retrieve the control the ASP-way: by looking in the <br />
            ' Page's Form collection <br />
            ' to find the name of a button control, that actually is the control <br />
            ' that submitted the page <br />
            Dim keyName As String<br />
            For Each keyName In targPage.Request.Form<br />
                Dim ctl As Control = targPage.FindControl(keyName)<br />
                ' if a control named as this key exists, <br />
                ' check whether it is a button - if it is, return it! <br />
                If Not ctl Is Nothing Then<br />
                    If TypeOf ctl Is Button Then<br />
                        Return ctl<br />
                    End If<br />
                End If<br />
            Next<br />
        End If<br />
<br />
        Return Nothing<br />
    End Function

There's also another related article available at http://www.eggheadcafe.com/articles/20050609.asp[^]

The idea for the VB.Net function GetPostbackControl was picked from another website that I don't recall right now. I hope above helps. Let me know your views.


Thanks,

Durlabh
GeneralRe: I think... a better version Pin
Simon McEnlly29-Jun-05 3:12
Simon McEnlly29-Jun-05 3:12 

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.