Приходится дважды нажимать кнопку в asp.net (после текстового поля автоответка) - PullRequest
11 голосов
/ 06 июля 2010

На странице, которую я имею:

<asp:TextBox runat="server" ID="EmailTextBox" AutoPostBack="true" OnTextChanged="EmailTextBox_Changed" />
<asp:Button runat="server" ID="SearchButton" OnClick="AddButton_Click" Text="add" />

В EmailTextBox_Changed он подсчитывает, сколько электронных писем можно найти, прежде чем выполнять поиск.

Проблема в том, что когда вы что-то вводитев EmailTextBox и нажмите на кнопку, вы должны дважды щелкнуть, чтобы получить фактические результаты.Это связано с тем, что первый щелчок выполняет часть «AutoPostBack» из текстового поля, а затем необходимо нажать еще раз, чтобы произошла обратная передача фактического щелчка.

Без удаления «AutoPostBack = true», какмогу ли я остановить это, если в этих обстоятельствах понадобится два клика?

Ответы [ 6 ]

2 голосов
/ 16 декабря 2010

Я тоже искал ответ на этот вопрос. В итоге я удалил все autopostback = true и сделал все действия с JavaScript, так же как и вы.

Тем не менее, одна из вещей, с которыми я экспериментировал до появления JavaScript, заключалась в том, чтобы поддерживать контроль после постбэка. Я заметил, что скрытое поле, которое я использовал для хранения имени элемента управления с последним фокусом, имеет имя кнопки поиска (мое - кнопка сохранения). Итак, хотя я до сих пор не уверен, как заставить функцию «поиска» запускать «автоматически», как это должно быть, что в основном состоит в том, чтобы последовательно связывать события обратной передачи как из текстового поля, так и кнопки, я МОГУ знать, что пользователь нажал эту кнопку до того, как произошла обратная передача (или попытался).

Итак, при обратной передаче у вас есть запуск вашего текстового поля, а затем метод Page_Load или любой другой метод цикла страницы, который вы хотите использовать, где вы можете проверить, какой последний элемент управления был в фокусе. При этом есть несколько способов обойти эту проблему.

От руки, вы можете добавить код в каждое событие, которое запускается из автостопа элемента управления, такого как текстовое поле и кнопка поиска, чтобы проверить имя элемента управления фокусировкой. Если элемент управления, у которого фокус был последним, НЕ является функцией автоматического возврата элемента управления, которую мы выполняем, мы можем установить для bool уровня страницы с именем Run_Controls_Method значение TRUE, в противном случае установите для него значение false. Таким образом, мы знаем, что мы должны запустить элемент управления, у которого был последний метод обратной передачи фокуса.

При загрузке страницы вы можете сделать что-то вроде:

if (Run_Controls_Method && hdfFocusControl.Value != "")
{
    switch(hdfFocusControl.Value)
    {
        case "btnSearch":
           btnSearch_OnClick(null, null);
           break;
        case etc.
    }
}

Способ реализации hdfHasFocus:

HTML:

<input id="hdfHasFocus" runat="server" type="hidden" />

HTML-код позади:

protected void Page_PreRender(object sender,EventArgs e)
{
   if (IsPostBack != true)
   {
       //Add the OnFocus event to all appropriate controls on the panel1 panel.         
       ControlManager.AddOnFocus(this.Controls,hdfHasFocus,true);
       //other code...
   }

   ControlManager.SetFocus(this.Controls,hdfHasFocus.Value,true);
}

ControlManager.cs связанный код:

        /// <summary>
    /// Adds the onfocus event to the UI controls on the controls in the passed in control list.
    /// </summary>
    /// <param name="controls">The list of controls to apply this event.</param>
    /// <param name="saveControl">The control whose .value will be set to the control.ID of the control which had focus before postback.</param>
    /// <param name="Recurse">Should this method apply onfocus recursively to all child controls?</param>
    public static void AddOnFocus(ControlCollection controls, Control saveControl, bool Recurse)
    {
        foreach (Control control in controls)
        {
            //To make the .Add a bit easier to see/read.
            string action = "";

            //Only apply this change to valid control types. 
            if ((control is Button) ||
                (control is DropDownList) ||
                (control is ListBox) ||
                (control is TextBox) ||
                (control is RadDateInput) ||
                (control is RadDatePicker) ||
                (control is RadNumericTextBox))
            {
                //This version ignores errors.  This results in a 'worse case' scenario of having the hdfHasFocus field not getting a 
                //   value but also avoids bothering the user with an error.  So the user would call with a tweak request instead of 
                //   and error complaint.
                action = "try{document.getElementById(\"" + saveControl.ClientID + "\").value=\"" + control.ClientID + "\"} catch(e) {}";

                //Now, add the 'onfocus' attribute and the built action string.
                (control as WebControl).Attributes.Add("onfocus", action);
            }

            //The 'onfocus' event doesn't seem to work for checkbox...use below.
            if (control is CheckBox)
            {
                //This version ignores errors.  This results in a 'worse case' scenario of having the hdfHasFocus field not getting a 
                //   value but also avoids bothering the user with an error.  So the user would call with a tweak request instead of 
                //   and error complaint.
                action = "try{document.getElementById(\"" + saveControl.ClientID + "\").value=\"" + control.ClientID + "\"} catch(e) {}";
                //In case there is already an attribute here for 'onclick' then we will simply try to add to it.
                action = action + (control as WebControl).Attributes["onclick"];

                //Now, add the event attribute and the built action string.                 
                (control as WebControl).Attributes.Add("onclick", action);
            }

            //You don't seem to be able to easily work the calendar button wiht the keyboard, and it seems made for
            //  mouse interaction, so lets set the tab index to -1 to avoid focus with tab.
            if (control is CalendarPopupButton)
            {
                (control as WebControl).Attributes.Add("tabindex", "-1");
            }

            //We also want to avoid user tab to the up and down spinner buttons on any RadNumericTextBox controls.
            if (control is RadNumericTextBox)
            {
                (control as RadNumericTextBox).ButtonDownContainer.Attributes.Add("tabindex", "-1");
                (control as RadNumericTextBox).ButtonUpContainer.Attributes.Add("tabindex", "-1");
            }

            //Recursively call this method if the control in question has children controls and we are told to recurse.
            if ((Recurse) && (control.HasControls()))
            {
                AddOnFocus(control.Controls, saveControl, Recurse);
            }
        }
    }

    /// <summary>
    /// Searches the ControlCollection passed in for a match on the ID name string passed in and sets focus on that control if it is found.
    /// </summary>
    /// <param name="controls">The collection of controls to search.</param>
    /// <param name="FocusToID">The ID of the control to set focus on.</param>
    /// <param name="recurse">Recursively search sub-controls in the passed in control collection?</param>        
    /// <returns>True means keep processing the control list.  False means stop processing the control list.</returns>
    public static bool SetFocus(ControlCollection controls, string FocusToID, bool recurse)
    {
        //Return if no control ID to work with.
        if (string.IsNullOrEmpty(FocusToID) == true)
        { return false; }

        //If we get here and don't have controls, return and continue the other controls if applicable.
        if (controls.Count <= 0)
        { return true; }

        foreach (Control control in controls)
        {
            //If this is the control we need AND it is Enabled, set focus on it.
            if (((control is GridTableRow) != true) &&  //GridTableRow.ClientID throws an error. We don't set focus on a 'Row' anyway.
                (control.ClientID == FocusToID) && 
                ((control as WebControl).Enabled))
            {
                control.Focus();
                //return to caller.  If we were recursing then we can stop now.
                return false;
            }
            else
            {
                //Otherwise, see if this control has children controls to process, if we are told to recurse.
                if ((recurse) && (control.HasControls()))
                {
                    bool _continue = SetFocus(control.Controls, FocusToID, recurse);
                    //If the recursive call sends back false, that means stop.
                    if (_continue != true)
                    { return _continue; }
                }
            }
        }

        //We are done processing all the controls in the list we were given...
        //  If we get here, then return True to the caller.  If this was a recursive call, then
        //  the SetFocus in the call stack above will be told to continue looking since we 
        //  didn't find the control in question in the list we were given.
        return true;
    }
1 голос
/ 05 декабря 2014

Введите приведенный ниже код в событии Page_Load, чтобы дважды не щелкнуть

BtnSaveAndPrint.Attributes.Add("onclick", "return confirm('Are you sure you Want to Save & Print?');")
1 голос
/ 22 октября 2010

Решением этой проблемы стала проверка на стороне клиента ... кажется, нет способа предотвратить это в противном случае

1 голос
/ 06 июля 2010

На самом деле вам не нужно нажимать на кнопку, чтобы произошло первое событие. Просто «оставьте» текстовое поле, т. Е. С «табуляцией» из него, чтобы произошел AutoPostBack.

Если вы хотите сделать оба в одной обратной передаче, просто удалите кнопку и сделайте то же, что и в AddButton_Click, также в событии Textbox_Change.

0 голосов
/ 17 сентября 2013

У меня была такая же проблема, я решил переместить код события клика в событие загрузки страницы и выполнить его в случае обратной передачи. И вообще не использовать событие щелчка.

protected void Page_Load(object sender, System.EventArgs e)
    {
        if (IsPostBack)
        {
             // put code here
        }
    }

вместо:

public void ButtonClick(object sender, EventArgs e)
    {
      //...
    }
0 голосов
/ 06 июля 2010

Вы могли бы избежать этого, не делая это на стороне сервера и используя Javascript.Вы также не опубликовали событие загрузки страницы.Вы проверяете, отправляет ли сообщение обратно или нет?

Еще один способ сделать это - это событие, которое происходит при нажатии кнопки, может быть вызвано из события TextChanged и избавиться от кнопки все вместе.

...