Установить фокус на любой элемент управления после PostBack - PullRequest
3 голосов
/ 06 сентября 2011

Сначала у меня есть 3 TextBox, DropDownList, CheckBox и 2 LinkButton в таблице. TextBoxes и DropDownList должны выполнять AutoPostBack, поскольку на стороне сервера выполняются некоторые вычисления, вызываемые OnTextChanged.

Моя проблема заключается в том, что после изменения содержимого любого элемента управления (для которого требуется PostBack) вы пытаетесь переместить фокус на любой другой элемент управления на странице (будь то вкладка или использование мыши для нажатия на любой другой элемент управления) фокус не перемещается к следующему элементу управления или элементу управления, на который вы нажали.

Я попытался использовать метод, который находит текущий элемент управления и на основе 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 голосов
/ 06 сентября 2011

Попробуйте сделать что-то подобное, чтобы сохранить фокус после обратной передачи:

/// <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;
}
0 голосов
/ 07 сентября 2011

Спасибо за помощь, она немного приблизила меня. Единственное, что мешало его правильной работе, - это то, что на моей странице есть некоторые переменные, которые переносятся с других страниц. Когда страница загружается, переопределение вызывает разрыв страницы, поскольку она не может найти эти элементы управления. Мне удалось решить эту проблему, добавив HiddenField на странице .aspx и добавив следующий код в функцию 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;
}

В итоге мне не пришлось вносить какие-либо изменения в код. Еще раз спасибо за помощь!

...