将焦点设置到PostBack后的任何控件

4

我有三个文本框、一个下拉列表框、一个复选框和两个链接按钮,它们都在一个表格中。由于服务器端需要进行一些计算(通过OnTextChanged调用),所以文本框和下拉列表框必须执行自动回发。

我的问题在于,在任何控件的内容(需要回发)更改后,当您尝试将焦点移动到页面上的其他控件时(无论是通过制表符还是使用鼠标单击其他控件),焦点不会移动到下一个控件或您单击的控件。

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

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

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

我已经进行了大量搜索,但没有能够找到解决此特定问题的任何解决方案,我找到的所有内容都涉及将焦点设置为下一个控件,而不是您想要获得焦点的控件。任何帮助将不胜感激。谢谢。

这是我用于基于TabIndex移动到下一个控件的代码,但在我的情况下不起作用。

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个回答

4

尝试通过以下方式在Postback后保持焦点:

/// <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;
}

你的意思是无法找到哪些控件?哪些控件? - James Johnson
我创建了一个新的解决方案,复制了问题并尝试了您的代码,它确实有效,但不幸的是在我的情况下导致页面崩溃。我添加了下面的代码,解决了我遇到的问题。再次感谢您的帮助! - Brian

0

感谢您的帮助,它确实让我更接近了解答案。唯一阻止正确工作的事情是我的页面有一些变量从其他页面传递过来。当页面加载时,覆盖会导致页面崩溃,因为它无法定位这些控件。我通过在.aspx页面上添加一个HiddenField并将以下代码添加到onload()函数中来解决了这个问题:

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

同时还要添加一个新的函数,该函数在每个文本框上调用:

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

最终我没有必要修改后台代码。再次感谢您的帮助!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接