On a page I have:
在我有一个页面上:
<asp:TextBox runat="server" ID="EmailTextBox" AutoPostBack="true" OnTextChanged="EmailTextBox_Changed" />
<asp:Button runat="server" ID="SearchButton" OnClick="AddButton_Click" Text="add" />
In EmailTextBox_Changed, it counts up how many emails can be found, before running the search.
在EmailTextBox_Changed中,它会在运行搜索之前计算可以找到的电子邮件数量。
The problem is, when you type something in EmailTextBox, and click on the button, you have to click twice to get the actual results up. This is because the first click is doing the "AutoPostBack" part from the text box, and then you have to click again to make the actual click postback to happen.
问题是,当您在EmailTextBox中键入内容并单击按钮时,您必须单击两次才能获得实际结果。这是因为第一次单击是从文本框中执行“AutoPostBack”部分,然后您必须再次单击以使实际的单击回发发生。
Without removing the "AutoPostBack=true", how can I stop it needing two clicks in these circumstances?
在不删除“AutoPostBack = true”的情况下,如何在这些情况下停止需要两次点击?
6 个解决方案
#1
2
I was looking for an answer to this issue as well. I ended up removing all autopostback=true and doing all the actions with JavaScript, same as you.
我也在寻找这个问题的答案。我最终删除了所有autopostback = true并使用JavaScript执行所有操作,与您一样。
However, one of the things I experimented with before the JavaScript was something to maintain control focus after a postback. I noticed the hidden field I used to store the name of the control that had the last focus DID have the name of the search button (mine is a save button). So, while I'm still not sure how to get the 'search' function to fire 'automatically' like it should, which is basically to chain the postback events from both the textbox AND the button together one after another, I CAN know that the user clicked that save button before the postback happened (or tried to).
但是,我在JavaScript之前尝试过的一件事就是在回发后保持控制焦点。我注意到我用来存储最后一个焦点的控件名称的隐藏字段DID具有搜索按钮的名称(我的是一个保存按钮)。所以,虽然我仍然不确定如何让“搜索”功能像它应该的那样“自动”发射,这基本上是将文本框和按钮的回发事件一个接一个地链接在一起,我知道用户在回发发生(或尝试)之前单击了该保存按钮。
So, what you have on postback is your textbox event firing, and then the Page_Load method, or whatever page cycle method you want to use, where you can check to see what the last control to have focus was. With this, there are several ways you could implement a work around.
因此,您在回发时所拥有的是您的文本框事件触发,然后是Page_Load方法,或者您想要使用的任何页面循环方法,您可以在其中查看要关注的最后一个控件是什么。有了这个,有几种方法可以实现一个解决方案。
Off hand, you could add code in every event that fires from a control autopostback, like the textbox and the search button, to check the name of the focus control. If the control that had focus last is NOT the control's autopostback function we are running, we can set a page level bool called 'Run_Controls_Method' to TRUE, else, set it to false. This way we know we should run the control that had last focus postback method.
另外,您可以在从控件自动回放触发的每个事件中添加代码,例如文本框和搜索按钮,以检查焦点控件的名称。如果最后焦点的控件不是我们正在运行的控件的autopostback函数,我们可以将名为'Run_Controls_Method'的页面级别bool设置为TRUE,否则将其设置为false。这样我们就知道我们应该运行具有最后焦点回发方法的控件。
On page load, you could do something like:
在页面加载时,您可以执行以下操作:
if (Run_Controls_Method && hdfFocusControl.Value != "")
{
switch(hdfFocusControl.Value)
{
case "btnSearch":
btnSearch_OnClick(null, null);
break;
case etc.
}
}
The way I implement the hdfHasFocus is:
我实现hdfHasFocus的方式是:
HTML:
HTML:
<input id="hdfHasFocus" runat="server" type="hidden" />
HTML code behind:
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 related code:
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;
}
#2
1
In fact, you don't have to click on the button to make the first event happen. Just 'leave' the textbox, i.e. with 'tabbing' out of it to make the AutoPostBack happen.
实际上,您不必单击按钮即可使第一个事件发生。只需“离开”文本框,即使用“tabbing”来实现AutoPostBack。
If you want to do both in a single postback just remove the Button and do the things you do in AddButton_Click also in the Textbox_Change event.
如果你想在一个回发中同时执行这两个操作,只需删除Button并在Textbox_Change事件中执行AddButton_Click中的操作。
#3
1
Making it a client side check was the solution to this...there doesn't seem to be a way to prevent it otherwise
让它成为客户端检查是解决方案......否则似乎没有办法防止它
#4
1
Write below code in Page_Load event to prevent twice click
在Page_Load事件中写下以下代码以防止两次单击
BtnSaveAndPrint.Attributes.Add("onclick", "return confirm('Are you sure you Want to Save & Print?');")
#5
0
You could avoid this by not doing it server side and using Javascript. You also didn't post your page load event. Are you checking if it post back or not ?
您可以通过不使用服务器端并使用Javascript来避免这种情况。您也没有发布您的页面加载事件。你在检查它是否回复?
Another way you could do this is the event that happens on the click of the button can be called from the TextChanged event and get rid of the button all together.
另一种方法是,可以从TextChanged事件中调用单击按钮时发生的事件,并一起删除按钮。
#6
0
I had the same problem, I decided to move the click event code to the page load event and execute it in case of postback. And not to use a click event at all.
我有同样的问题,我决定将点击事件代码移动到页面加载事件并在回发的情况下执行它。而根本不使用点击事件。
protected void Page_Load(object sender, System.EventArgs e)
{
if (IsPostBack)
{
// put code here
}
}
instead of :
代替 :
public void ButtonClick(object sender, EventArgs e)
{
//...
}
#1
2
I was looking for an answer to this issue as well. I ended up removing all autopostback=true and doing all the actions with JavaScript, same as you.
我也在寻找这个问题的答案。我最终删除了所有autopostback = true并使用JavaScript执行所有操作,与您一样。
However, one of the things I experimented with before the JavaScript was something to maintain control focus after a postback. I noticed the hidden field I used to store the name of the control that had the last focus DID have the name of the search button (mine is a save button). So, while I'm still not sure how to get the 'search' function to fire 'automatically' like it should, which is basically to chain the postback events from both the textbox AND the button together one after another, I CAN know that the user clicked that save button before the postback happened (or tried to).
但是,我在JavaScript之前尝试过的一件事就是在回发后保持控制焦点。我注意到我用来存储最后一个焦点的控件名称的隐藏字段DID具有搜索按钮的名称(我的是一个保存按钮)。所以,虽然我仍然不确定如何让“搜索”功能像它应该的那样“自动”发射,这基本上是将文本框和按钮的回发事件一个接一个地链接在一起,我知道用户在回发发生(或尝试)之前单击了该保存按钮。
So, what you have on postback is your textbox event firing, and then the Page_Load method, or whatever page cycle method you want to use, where you can check to see what the last control to have focus was. With this, there are several ways you could implement a work around.
因此,您在回发时所拥有的是您的文本框事件触发,然后是Page_Load方法,或者您想要使用的任何页面循环方法,您可以在其中查看要关注的最后一个控件是什么。有了这个,有几种方法可以实现一个解决方案。
Off hand, you could add code in every event that fires from a control autopostback, like the textbox and the search button, to check the name of the focus control. If the control that had focus last is NOT the control's autopostback function we are running, we can set a page level bool called 'Run_Controls_Method' to TRUE, else, set it to false. This way we know we should run the control that had last focus postback method.
另外,您可以在从控件自动回放触发的每个事件中添加代码,例如文本框和搜索按钮,以检查焦点控件的名称。如果最后焦点的控件不是我们正在运行的控件的autopostback函数,我们可以将名为'Run_Controls_Method'的页面级别bool设置为TRUE,否则将其设置为false。这样我们就知道我们应该运行具有最后焦点回发方法的控件。
On page load, you could do something like:
在页面加载时,您可以执行以下操作:
if (Run_Controls_Method && hdfFocusControl.Value != "")
{
switch(hdfFocusControl.Value)
{
case "btnSearch":
btnSearch_OnClick(null, null);
break;
case etc.
}
}
The way I implement the hdfHasFocus is:
我实现hdfHasFocus的方式是:
HTML:
HTML:
<input id="hdfHasFocus" runat="server" type="hidden" />
HTML code behind:
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 related code:
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;
}
#2
1
In fact, you don't have to click on the button to make the first event happen. Just 'leave' the textbox, i.e. with 'tabbing' out of it to make the AutoPostBack happen.
实际上,您不必单击按钮即可使第一个事件发生。只需“离开”文本框,即使用“tabbing”来实现AutoPostBack。
If you want to do both in a single postback just remove the Button and do the things you do in AddButton_Click also in the Textbox_Change event.
如果你想在一个回发中同时执行这两个操作,只需删除Button并在Textbox_Change事件中执行AddButton_Click中的操作。
#3
1
Making it a client side check was the solution to this...there doesn't seem to be a way to prevent it otherwise
让它成为客户端检查是解决方案......否则似乎没有办法防止它
#4
1
Write below code in Page_Load event to prevent twice click
在Page_Load事件中写下以下代码以防止两次单击
BtnSaveAndPrint.Attributes.Add("onclick", "return confirm('Are you sure you Want to Save & Print?');")
#5
0
You could avoid this by not doing it server side and using Javascript. You also didn't post your page load event. Are you checking if it post back or not ?
您可以通过不使用服务器端并使用Javascript来避免这种情况。您也没有发布您的页面加载事件。你在检查它是否回复?
Another way you could do this is the event that happens on the click of the button can be called from the TextChanged event and get rid of the button all together.
另一种方法是,可以从TextChanged事件中调用单击按钮时发生的事件,并一起删除按钮。
#6
0
I had the same problem, I decided to move the click event code to the page load event and execute it in case of postback. And not to use a click event at all.
我有同样的问题,我决定将点击事件代码移动到页面加载事件并在回发的情况下执行它。而根本不使用点击事件。
protected void Page_Load(object sender, System.EventArgs e)
{
if (IsPostBack)
{
// put code here
}
}
instead of :
代替 :
public void ButtonClick(object sender, EventArgs e)
{
//...
}