Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to maintain tab order after postback

Tags:

c#

asp.net

The requirement is for some calculation to happen on entering a value in the textbox and since calculation is same ontextchanged is linked to the same event. When I tab out it neatly goes to next control and does a postback to Calculate.

Now after the postback and the server side is called and executed, the tab order is messed up and on tab it does not bring focus to the correct control. It always points to the URL in the browser window.

Please let me know how do i retrieve the control which should be next in focus after the postback using the tabIndex.

  <asp:TextBox ID="txtDiscount" runat="server" CssClass="NormalTextBox" TabIndex="45"
                                    MaxLength="3" OnTextChanged="btnCalculatePrice_Click" AutoPostBack="True"></asp:TextBox>


  protected void btnCalculatePrice_Click(object sender, EventArgs e)
    {....

}

I tried the below code but didnt know how to fetch the exact control

   if(sender!=null)
        {
            WebControl reqCtrl = (WebControl)sender;
            int taborder = reqCtrl.TabIndex;
            int nexttabOrder = taborder + 1;

        }
like image 447
Nisha_Roy Avatar asked May 16 '11 10:05

Nisha_Roy


2 Answers

Use below code in order to set focus to next control after post back.

protected void Page_Load(object sender, EventArgs e)
{
if (Page.IsPostBack)
{
WebControl wcICausedPostBack = (WebControl)GetControlThatCausedPostBack(sender as Page);
int indx = wcICausedPostBack.TabIndex;
var ctrl = from control in wcICausedPostBack.Parent.Controls.OfType<WebControl>()
where control.TabIndex > indx
select control;
ctrl.DefaultIfEmpty(wcICausedPostBack).First().Focus();
}
}
protected Control GetControlThatCausedPostBack(Page page)
{
Control control = null;
string ctrlname = page.Request.Params.Get("__EVENTTARGET");
if (ctrlname != null && ctrlname != string.Empty)
{
control = page.FindControl(ctrlname);
}
else
{
foreach (string ctl in page.Request.Form)
{
Control c = page.FindControl(ctl);
if (c is System.Web.UI.WebControls.Button || c is System.Web.UI.WebControls.ImageButton)
{
control = c;
break;
}
}
}
return control;
}
like image 192
MUS Avatar answered Sep 22 '22 00:09

MUS


Here is a similar (app code) solution that works for controls that may not necessarily share the same parent. It assumes the tab indexes are exactly 1 number apart.

protected void Page_Load(object sender, EventArgs e)
{
    if (IsPostBack)
    {
        SetFocusAfterPostBack();
    }
}

public static void SetFocusAfterPostBack()
{
    var page = HttpContext.Current.Handler as Page;
    if (page == null)
    {
        return;
    }
    var postBackCtl = page.FindControl(HttpContext.Current.Request.Form["__EVENTTARGET"]) as WebControl;
    if (postBackCtl == null || postBackCtl.TabIndex == 0)
    {
        return;
    }
    var ctl = GetCtlByTabIndex(page, postBackCtl.TabIndex + 1);
    if (ctl != null)
    {
        ctl.Focus();
    }
}
private static WebControl GetCtlByTabIndex(Control ParentCtl, int TabIndex)
{
    foreach (Control ctl in ParentCtl.Controls)
    {
        var webCtl = ctl as WebControl;
        if (webCtl != null)
        {
            if (webCtl.TabIndex == TabIndex)
            {
                return webCtl;
            }
        }
        var retCtl = GetCtlByTabIndex(ctl, TabIndex);
        if (retCtl != null)
        {
            return retCtl;
        }
    }
    return null;
}
like image 20
Bolo Avatar answered Sep 23 '22 00:09

Bolo