Настройка кнопки по умолчанию в Ajaxified Wizard Control

У меня есть элемент управления Wizard в моей веб-форме ASP.NET. Я устанавливаю кнопку по умолчанию на каждом шаге в событии ApplicationWizard PreRender в коде программной части следующим образом:

Page.Form.DefaultButton = ApplicationWizard.FindControl("StepNavigationTemplateContainerID").FindControl("StepNextButton").UniqueID;

Это работает отлично, но когда я ajaxify элемент управления Wizard, он не работает. Кнопка по умолчанию настроена на элемент управления, который я указываю при начальной загрузке формы (StartNextButton), но не обновляется до StepNextButton на других шагах. Что я делаю неправильно?


person Mike Cole    schedule 29.07.2009    source источник


Ответы (6)


Через день или два, когда я выдергивал волосы, мне удалось взломать это ... надеюсь, это поможет другим, таким же разочарованным, как и я:

Любой, кто нашел этот пост, знает, что интуитивно понятный ответ здесь, установка кнопки формы по умолчанию на кнопку «Далее» вашего мастера, ничего не делает. Итак, следующий логический шаг — попытаться обойти проблему, нажав кнопку от имени пользователя. Предположим, я прикрепил приведенный ниже обработчик к моему текстовому полю из кода программной части и что myButtonId — это идентификатор кнопки, которая мне нужна по умолчанию:

            function textKeyDown(e) {
                if (e.keyCode == 13) {
                    var myBtn = $get(myButtonId);
                    myBtn.click();
                }
            }

Вы могли бы подумать, что описанное выше будет работать просто отлично, но, как оказалось, принуждение кнопки Wizard к нажатию создавало чрезвычайно скрытый конфликт — первая кнопка на странице также нажималась, переопределяя первоначальный щелчок кнопки, который я принудительно нажал с помощью скрипта и создавая очень странные результаты. В моем случае первая кнопка на главной странице — это кнопка с надписью «Домой», и когда пользователь нажимает ее, он возвращается на свою домашнюю страницу. Таким образом, в моих попытках заставить кнопку Мастера «Далее» щелкнуть, я возвращался обратно на свою домашнюю страницу, что казалось безо всякой причины. После присоединения к PageRequestManager.initializeRequest я смог увидеть, что у меня было две отдельные обратные передачи: 1 для принудительного нажатия кнопки мастера и 1 для кнопки, которой в то время даже не было на моем радаре - кнопки домашней страницы.

Итак, короче говоря, если я обновлю кнопку формы по умолчанию (Page.Form.DefaultButton) из кода позади, а затем выпущу этот скрипт из кода позади и также сошлюсь на него из моего текстового поля, все работает просто отлично:

    public static void ExampleAssignDefaultButton(WizardStepBase activeWizardStep, TextBox myTextBox, IButtonControl myButton)
    {
        // create the format string for the script
        string javaScript = @"function defaultButton(src, evt){{
                                if(evt.keyCode == 13){{
                                    var btn = $get('{0}');
                                    setTimeout(new function() {{ btn.click(); }}, 5);
                                }}
                            }}";

        // format it ...
        javaScript = String.Format(javaScript, ((WebControl)myButton).ClientID);
        // register it...
        ScriptManager.RegisterClientScriptBlock(activeWizardStep, activeWizardStep.GetType(), "defaultButton", javaScript, true);

        // assign it to my textbox
        myTextBox.Attributes.Add("onkeydown", "defaultButton(this, event);");

        // also update the form's default button:
        myTextBox.Page.Form.DefaultButton = ((WebControl)myButton).UniqueID;
    }

Стоит отметить, что я всегда вызываю вышеуказанный метод из события OnPreRender активного шага мастера. Также стоит отметить, что, поскольку у меня есть только одно текстовое поле на шаг в моем мастере, мне нужно было назначить это поведение только одному элементу управления. Я не пробовал это исправление, чтобы поймать нажатие клавиши Enter на всей странице, хотя я не могу представить, что оно будет вести себя по-другому в этом контексте. Вам, вероятно, не нужно ловить клавишу Enter на каждом элементе управления в вашем мастере, если у вас много входных данных на шаг.

Итак, у вас есть это - всего 12 часов устранения неполадок, чтобы сделать то, что должно было занять около 10 минут.

Удачного кодирования.

B

person Brian    schedule 20.07.2011
comment
У меня есть эта проблема. Я пытаюсь решить на основе вашего ответа, но просто не могу заставить его работать. Javascript добавлен нормально, но страница по-прежнему реагирует на кнопку главной страницы, а не на кнопку «Далее»....? Любые идеи? - person Mad Pierre; 13.02.2012
comment
Привет @Mad Pierre - ты пробовал в нескольких браузерах? Мой ответ здесь может быть немного устаревшим для таких браузеров, как Chrome, которые решили, что click() не может быть вызван, и вместо этого вам нужно имитировать щелчок мышью, генерируя события DOM2... - person Brian; 15.02.2012
comment
Еще нет. Сначала я пытаюсь использовать IE (9). Вы видели мой другой комментарий выше: скрипт работает, если я добавлю предупреждение? - person Mad Pierre; 16.02.2012
comment
Привет @MadPierre - может быть, отключить кнопку «Домой» перед вызовом .click()? Мне нужно увидеть ваш код, чтобы узнать, что именно происходит, но что-то определенно вызывает нажатие на другую вашу кнопку, и отключение кнопки предотвратит срабатывание щелчка - отредактируйте - только что увидел, что вы исправили свою проблему - рад, что вы прибил это :), возможно, отключение поможет кому-то еще, читающему эту ветку, поэтому я оставлю это в такт... - person Brian; 01.03.2012

Спасибо, Брайан, ваш скрипт помог мне настроить свой собственный при использовании RadAjax, нескольких пользовательских элементов управления и нескольких типов панелей. Вы можете упростить defaultButton, передав идентификатор кнопки из элемента управления, а не в скрипт.

На странице:

function defaultButton(btnid, src, evt) {
    if (evt.keyCode == 13) {
        var btn = $get(btnid);
        setTimeout(new function () { btn.click(); }, 5);
    }
}

В коде:

Private Sub WizardStep_PreRender(sender As Object, e As System.EventArgs) Handles wsUserPass.PreRender, wsCompanyCode.PreRender, wsSetPassword.PreRender
    Dim button As WebControl = Nothing
    Dim activeWizardStep As WizardStepBase = CType(sender, WizardStepBase)
    Select Case activeWizardStep.StepType
        Case WizardStepType.Step
            button = activeWizardStep.FindControl("StepNavigationTemplateContainerID").FindControl("StepNextButton")
        Case WizardStepType.Start
            button = activeWizardStep.FindControl("StartNavigationTemplateContainerID").FindControl("StartNextButton")
        Case WizardStepType.Finish
            button = activeWizardStep.FindControl("FinishNavigationTemplateContainerID").FindControl("FinishButton")
    End Select
    If button Is Nothing Then Return
    Dim ctrls = FindControls(Of RadTextBox)(activeWizardStep)
    For Each ctrl In ctrls
        ctrl.Attributes.Add("onkeydown", String.Format("defaultButton('{0}', this, event);", button.ClientID))
    Next
    pnlMain.DefaultButton = button.UniqueID
End Sub

Public Shared Function FindControls(Of T)(ctrl As Control) As List(Of T)
    Dim controls As New List(Of T)
    If ctrl.Controls.Count > 0 Then
        For Each subctrl In ctrl.Controls
            If [Type].ReferenceEquals(GetType(T), subctrl.GetType()) Then
                controls.Add(subctrl)
            Else
                controls.AddRange(FindControls(Of T)(subctrl))
            End If
        Next
    End If
    Return controls
End Function

(Обратите внимание, у меня не работал UniqueID, пришлось поменять на ClientID)

person Jack    schedule 22.09.2011
comment
Это странно! Основываясь на моем коде С# на вашем, кнопка по умолчанию работает, только если у меня есть предупреждение в конце функции javascript! т.е. если я поставлю функцию defaultButton(btnid, src, evt) { if (evt.keyCode == 13) { var btn = $get(btnid); setTimeout (новая функция () { btn.click(); }, 5); оповещение('тест'); } } Оно работает! Однако удаление предупреждения («тест») приводит к тому, что моя кнопка домашней страницы по умолчанию выигрывает. У кого-нибудь есть идеи? Это потратило пару дней для меня до сих пор..... - person Mad Pierre; 13.02.2012

Попробуйте ScriptManager.SetFocus.

person Artem Koshelev    schedule 03.08.2009

Каково определение кнопки по умолчанию? Если это кнопка, которая должна вызываться, когда вы находитесь в поле текстовой формы (тип ввода = текст) и нажимаете ввод, то в каждом браузере это первая кнопка отправки или изображения в форме (тип ввода = отправка | изображение) если есть.

Что вы можете сделать, так это добавить клиентский скрипт ко всем элементам управления, к которым применяется такое правило, как форма отправки на [enter] (например, на input type="text").

Пример на стороне сервера (можно использовать в Form_Init) просто для идеи:

SomeTextBox.Attributes.Add("onkeydown",
    "if((event.keyCode&&event.keyCode==13)){" +
    Page.ClientScript.GetPostBackEventReference(StepNextButton, "") +
    ";return false;}" +
    "if((event.keyCode&&event.keyCode==27)){" +
    Page.ClientScript.GetPostBackEventReference(CancelButton, "") +
    ";return false;}");

keyCode==13 – это клавиша ввода
keyCode==27 – это клавиша Escape

person Viktor Jevdokimov    schedule 06.08.2009

Я думаю, что я, наконец, взломал это! Тот факт, что предупреждающее сообщение (отладка) в javascript заставило его работать, указало мне правильное направление...

Мне пришлось добавить пару строк в javascript, чтобы заставить его работать, чтобы мой метод выглядел так:

private void SetDefaultButtonScript(WizardStepBase activeWizardStep, IButtonControl myButton)
    {
        string clientID = ((WebControl)myButton).ClientID;
        string uniqueID = ((WebControl)myButton).UniqueID;

        // create the format string for the script 
        string javaScript = @"function defaultButton(btnid, evt) {{ 
                                if (evt.keyCode == 13) {{ 
                                    __doPostBack('{0}', '');
                                    var btn = $get('{1}');
                                    btn.focus();
                                    return;
                                }} 
                            }} 
                            ";
        javaScript = String.Format(javaScript, uniqueID, clientID); 

        // register it... 
        ScriptManager.RegisterClientScriptBlock(activeWizardStep, activeWizardStep.GetType(), "defaultButton", javaScript, true);

        foreach (Control c in activeWizardStep.Controls)
        {
            if (c is TextBox)
            {
                ((TextBox)c).Attributes.Add("onkeydown", "defaultButton(this, event);"); 
            }
            //TODO child controls of controls to find all text boxes, any other controls etc
        }

        Page.Form.DefaultButton = uniqueID;
    } 

Я использую __doPostBack вместо щелчка, но это не проблема.

person Mad Pierre    schedule 10.02.2012

Я не думаю, что вам нужны какие-либо сценарии здесь. Проблема в том, что на странице есть несколько кнопок отправки. Таким образом, вы должны указать asp.net, какой из них вы хотите использовать в качестве отправки по умолчанию. И вы должны сообщить об этом в нужное время в жизненном цикле страницы. Я не уверен, что это оптимально, но кажется, что это работает в событии PreRender. Базовый мастер ajaxified, в который добавлен только следующий код, похоже, использует правильную кнопку:

Protected Overrides Sub OnPreRender(ByVal e As System.EventArgs)
    MyBase.OnPreRender(e)
    Select Case LoginWizard.ActiveStep.StepType
        Case WizardStepType.Start
            Page.Form.DefaultButton = LoginWizard.FindControl("StartNavigationTemplateContainerID").FindControl("NextStart").UniqueID
        Case WizardStepType.Step
            Page.Form.DefaultButton = LoginWizard.FindControl("StepNavigationTemplateContainerID").FindControl("NextStep").UniqueID
        Case WizardStepType.Finish
            Page.Form.DefaultButton = LoginWizard.FindControl("FinishNavigationTemplateContainerID").FindControl("LastStep").UniqueID
    End Select
End Sub
person Milimetric    schedule 05.06.2012