Ответ 1
Сделать это клиентской проверкой было решением этого... там, похоже, не существует способа предотвратить это иначе
На странице у меня есть:
<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", как я могу остановить его при необходимости в два клика?
Сделать это клиентской проверкой было решением этого... там, похоже, не существует способа предотвратить это иначе
Я искал ответ на этот вопрос. Я закончил удаление всех autopostback = true и выполнил все действия с JavaScript, как и вы.
Тем не менее, одна из вещей, которые я экспериментировал перед JavaScript, была чем-то, что позволило сохранить фокус управления после обратной передачи. Я заметил скрытое поле, которое я использовал для хранения имени элемента управления, у которого последний фокус DID имел имя кнопки поиска (моя кнопка сохранения). Итак, пока я до сих пор не знаю, как заставить функцию "поиска" запускать "автоматически", как это должно быть, что в основном заключается в том, чтобы связать события обратной передачи как из текстового поля, так и из кнопки вместе друг за другом, я МОГУ знать, что пользователь нажал кнопку "Сохранить" до того, как произошла (или попыталась) выполнить обратную передачу.
Итак, что у вас есть при обратной передаче, это стрельба по событию в текстовом поле, а затем метод 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;
}
На самом деле вам не нужно нажимать на кнопку, чтобы произошло первое событие. Просто "оставьте" текстовое поле, т.е. С помощью "tabbing", чтобы сделать AutoPostBack.
Если вы хотите сделать оба в одной обратной почте, просто удалите Button и сделайте то, что вы делаете в AddButton_Click, также в событии Textbox_Change.
Запишите ниже код в событии Page_Load, чтобы дважды дважды щелкнуть
BtnSaveAndPrint.Attributes.Add("onclick", "return confirm('Are you sure you Want to Save & Print?');")
Вы можете избежать этого, не выполняя его на стороне сервера и используя Javascript. Вы также не опубликовали событие загрузки страницы. Проверяете ли вы его обратно или нет?
Другой способ, которым вы могли бы это сделать, - это событие, которое происходит при нажатии кнопки, можно вызвать из события TextChanged и полностью избавиться от кнопки.
У меня была такая же проблема, я решил переместить код события click в событие загрузки страницы и выполнить его в случае обратной передачи. И не использовать событие click вообще.
protected void Page_Load(object sender, System.EventArgs e)
{
if (IsPostBack)
{
// put code here
}
}
вместо:
public void ButtonClick(object sender, EventArgs e)
{
//...
}