在PostBack之后将焦点设置为任何控件

时间:2011-09-06 16:08:13

标签: c# asp.net visual-studio-2008 webforms client-side

首先,我在表中有3个TextBox,一个DropDownList,一个CheckBox和2个LinkBut​​tons。 TextBoxes和DropDownList必须执行AutoPostBack,因为在服务器端进行了一些由OnTextChanged调用的计算。

我的问题是,在任何Control(需要PostBack)的内容发生变化后,您尝试将焦点移动到页面上的任何其他Control(无论是Tab键还是使用鼠标点击任何其他Control)焦点不会移动到您单击的下一个Control或Control。

我尝试使用找到当前Control的方法并基于TabIndex,添加1将焦点移动到下一个控件。这里的问题是它不允许在除了具有下一个TabIndex的控件之外的任何其他控件上设置焦点。这里更好地解释一下这种情况的一个例子。

示例:我有TextBox1,TextBox2和TextBox3。我更改了TextBox2中的内容,然后想要向后移动到TextBox1。当我单击TextBox1时,焦点设置为TextBox3,因为代码使用TabIndex的顺序。 **这里的一个关键因素是TextBox1在服务器端代码触发之前获得焦点,但随后失去焦点并将其设置在TextBox3上**

对我来说,似乎可以实现的唯一方法是在客户端添加一个函数,在发生PostBack之前找到具有焦点的Control,然后在服务器端代码完成后重置该控件上的焦点。似乎我在服务器端做的任何事都不会起作用,因为当发生这种情况时焦点已经丢失。

我搜索过但搜索过但未能找到解决此问题的任何方法,我发现的所有内容都涉及将焦点设置到NEXT控件而不是您想要关注的控件。任何帮助将不胜感激。提前谢谢。

以下是我用于根据TabIndex移动到下一个Control的代码,但这在我的情况下不起作用。

protected void Page_Load(object sender, EventArgs e)
    {
        WebControl ctrl = GetPostBackControl() as WebControl;
        if (ctrl != null && !SetNextFocus(Controls, ctrl.TabIndex + 1)) { ctrl.Focus(); }
    }

public Control GetPostBackControl()
    {
        Control control = null;

        string ctrlname = Request.Params.Get("__EVENTTARGET");
        if (ctrlname != null && ctrlname != string.Empty)
        {
            control = FindControl(ctrlname);
            control.Focus();
        }
        else
        {
            foreach (string ctl in Request.Form)
            {
                Control c = FindControl(ctl);
                if (c is Button)
                {
                    control = c;
                    break;
                }
            }
        }
        return control;
    }

    private bool SetNextFocus(ControlCollection controls, int tabIndex)
    {
        foreach (Control control in controls)
        {
            if (control.HasControls())
            {
                bool found = SetNextFocus(control.Controls, tabIndex);
                if (found) { return true; }
            }

            WebControl webControl = control as WebControl;
            if (webControl == null) { continue; }
            if (webControl.TabIndex != tabIndex) { continue; }

            webControl.Focus();
            return true;
        }

        return false;
    }

2 个答案:

答案 0 :(得分:4)

尝试做这样的事情以在回发后保持焦点:

/// <summary>
/// Overrides the OnLoad event moves the cursor to the appropriate control.
/// </summary>
/// <param name="e"></param>
protected override void OnLoad(EventArgs e)
{
    base.OnLoad(e);

    int currentTabIndex = 1;
    WebControl postBackCtrl = (WebControl)GetControlThatCausedPostBack(Page);    

    foreach (WebControl ctrl in Panel1.Controls.OfType<WebControl>())
    {
        ctrl.TabIndex = (short)currentTabIndex;
        if (postBackCtrl != null)
        {
            if (ctrl.TabIndex == postBackCtrl.TabIndex + 1)
                ctrl.Focus();
        }
        currentTabIndex++;
    }                                        
}


/// <summary>
/// Retrieves the control that caused the postback.
/// </summary>
/// <param name="page"></param>
/// <returns></returns>
private Control GetControlThatCausedPostBack(Page page)
{
    //initialize a control and set it to null
    Control ctrl = null;

    //get the event target name and find the control
    string ctrlName = Page.Request.Params.Get("__EVENTTARGET");
    if (!String.IsNullOrEmpty(ctrlName))
        ctrl = page.FindControl(ctrlName);

    //return the control to the calling method
    return ctrl;
}

答案 1 :(得分:0)

感谢您的帮助,它确实让我更近了一点。唯一阻止它正常工作的是我的页面有一些变量从其他页面转移。页面加载时,覆盖会导致页面中断,因为它无法找到这些控件。我能够通过在.aspx页面上添加HiddenField并将以下代码添加到onload()函数来解决问题:

if (document.getElementById("HiddenField1").value != "") { 
    var contr = document.getElementById(document.getElementById"HiddenField1").value);
    contr.focus();
    document.getElementById("HiddenField1").value = "";
} 

以及添加在每个TextBox上调用的新函数:

function tabFocus(e) {
    document.getElementById("HiddenField1").value = e.id;
}

我最终不必对后面的代码进行任何更改。再一次,谢谢你的帮助!