1. Original Entry + Comments2. Write a Comment3. Preview Comment
New comments for this entry are disabled.


October 28, 2003  |  Default buttons  |  35830 hit(s)

<Update date=10 April 2005>This entry gets hit a lot, so I feel obliged to point to some other resources that address this problem. Here are some links:
  • First, see all the comments.
  • Colt Kwong tried this and it didn't work for him. He suggests another approach.
  • Someone reported that Raj Kaimal's solution works for them.
</Update>

<Update date=4 May 2006> Another update -- Matthew Saunders leaves this comment:
If you're playing in the wonderful land of Asp.Net 2.0 then consider using the form or panel DefaultButton property.

Visit :

http://harishmvp.blogspot.com/2006/04/aspnet-20-enter-key-default-submit.html


The link says it all.
I'll also note that the docs say it all. :-)

</Update>

A day for blogging ASP.NET stuff, I guess. As a lot of people know and/or have experienced, an ASP.NET page with a single textbox on it doesn't work the way you'd want. (An example would be this very blog, which has a single text box -- the Search box.) Ideally, you type something in and hit Enter; the page should then be submitted and a Click handler invoked.

There seems to be a bug in Internet Explorer. If there's only one textbox on the page, IE submits the page all right, but it neglects to send along information about the button, so no Click handler is invoked. If there is more than one textbox, IE submits the form and "clicks" the first button on the page.

Although the circumstances would seem to be rare -- IE + only one textbox on the page -- the question comes up pretty frequently on forums. Often enough, in fact, that Andy Miller has created a (free) custom control he calls DefaultButtons that solves this problem. Andy's control uses a fair bit of JavaScript to accomplish its task; the script covers a lot of cases, such as integrating with validation on the page. Because Andy's control is a compiled Web server control, the user doesn't have to worry about any of the code; that's injected automatically by the control.

The issue came up yet again today on the aspalliance listserv. Andy and one or two other people pointed the poster to the DefaultButtons control. However, another poster, a guy by the name of Donald Cote, suggested that an easy fix would be to simply add this to the Page_Load handler:
Page.RegisterHiddenField("__EVENTTARGET", ButtonName)
where ButtonName is the name of the button whose Click event you want to fire.

This technique leverages the way ASP.NET works with controls such as the LinkButton and Calendar control, or with AutoPostBack controls. Those controls cause the page to be posted when clicked, even though they are not buttons. For this to happen, ASP.NET does three things. First, it adds a hidden field to the page named _EVENTTARGET. ASP.NET also adds some client script to the page (the __doPostBack function) that performs a submit of the form. Finally, it injects client script into each control (or in the case of Calendar, into each cell of the table it generates) that invokes that __doPostBack function when the control is clicked (or whatever), passing to it the name of the control in question. Thus this is what's rendered for an auto-postback CheckBox control:
<input id="CheckBox1" type="checkbox" name="CheckBox1"
onclick="__doPostBack('CheckBox1','')"
language="javascript" /><label for="CheckBox1">Check1</label>
The __doPostBack function takes the value passed to it and makes it the value of the __EVENTTARGET hidden field and then submits the page. The upshot is that when page is submitted, ASP.NET gets a hidden field named __EVENTTARGET; if that hidden field has a value, ASP.NET can figure out what control caused the form to be submitted.

Pant-pant. This sure got longer than I'd intended. The technique that Donald Cote suggested preempts the hidden field that ASP.NET normally adds to the page and essentially hard-codes the hidden field to always submit the name of your chosen control. This works out quite neatly. If the page is submitted without any click event, ASP.NET accepts the name of your control as the sender. If you click a button on the page, ASP.NET ignores the hidden field in favor of the actual button click. If you have other controls on the page that invoke __doPostBack, then __doPostBack sets the value of the hidden field, overwriting your default value.

You can see this in action by creating a page that has some buttons, a LinkButton, a Calendar, and the aforementioned auto-postback CheckBox control. Then add this code to the page, which displays the information that ASP.NET gets when the page is submitted:
Sub Page_Load()
Page.RegisterHiddenField("__EVENTTARGET", "Button2")
Dim i As Integer
For i = 0 To Request.Form.Count - 1
Response.Write("Form: " & Request.Form.Keys(i) & ", value: " _
& Request.Form(i) & "<br>")
Next
End Sub

Sub Button_Click(sender as Object, e as EventArgs)
Dim b As Button = CType(sender, Button)
Label1.Text = "You clicked " & b.ID
End Sub
P.S. I've added this little hack to the blog so that the Search button does now work the way I want it to.




Shawn   24 Nov 03 - 12:19 PM

Mike,

I have a follow-up question based on your sample.

Assume I have 2 web control buttons. They can invoke __doPostBack. So at the page load, I will know who caused the PostBack. But the code snippets don't work as I expect. I recall, in the article, you said "If you have other controls on the page that invoke __doPostBack, then __doPostBack sets the value of the hidden field, overwriting your default value." So I wonder if you can help me out. Thanks.

Here is code snippets.

Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
'Put user code to initialize the page here
Page.RegisterHiddenField("__EVENTTARGET", "FakeButton")

If Request.Form("__EVENTTARGET") = "Button1" Then
'do one sth
ElseIf Request.Form("__EVENTTARGET") = "Button2" Then
'do another sth
End If

End Sub

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim b As Button = CType(sender, Button)
Label1.Text = "You clicked " & b.ID
End Sub

Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
Label1.Text = "You clicked " & sender.ID
End Sub







 
Mike   24 Nov 03 - 5:58 PM

Hi, Shawn. Button controls don't invoke __doPostBack. Instead, they render as Submit buttons, and the browser when a button is clicked, the browser submits the form without running any client script. The __doPostback trick is used only for controls (like LinkButtons, which render as anchor tags) that do not ordinarily submit, hence need some help to do so. It is only for *those* that you can extract the sender control from Request.Form.

Does this help? I might not be understanding your question properly.


 
Shawn   25 Nov 03 - 7:10 AM

Hi, Mike. Thanks for your reply. As Button controls don't invoke __doPostBack, how can I know which button invokes the postback on the page_load? Based on your comments, Request.Form("__EVENTTARGET") might not be helpful in this case.
Thanks.


 
Les Kelly   18 Feb 04 - 2:40 PM

I tried the method you mentioned here but it didn't work for me. The page I tried it on has several other <asp:Button> objects on it. An article at http://www.allasp.net/enterkey.aspx indicates that it will not work in this instance. What I actually want is for no event to fire when the user presses enter. What I ended up doing is putting a button that has a white fore and background at the top of the page. It can't be seen and if the user hits enter it still submits but at least no other action is taken. It's a pretty lame way around it so if you have any other suggestions I'd be glad to try them.
Thanks.


 
Mike   18 Feb 04 - 11:11 PM

I'm not sure I understand exactly what you're doing -- are you typing in a (single-line) textbox and want to prevent Enter from submitting the form?

If so, you could do a little client-side hack that absorbs the Enter key in the textbox. Do this in Page_Load:

Sub Page_Load()
TextBox1.Attributes.Add("onkeypress", "TestKeys()")
End Sub

And then add this client script to the page:

<script language="javascript">
function TestKeys()
{
if(event.keyCode == 13)
event.returnValue=false;
}
</script>

Just another possibility. (And again, assuming I understand correctly what you're trying to do.)


 
Anonymous   19 Feb 04 - 12:49 PM

Thats not exactly what I had in mind. I have a user control with buttons to navigate between pages, another user control to navigate between records, and a third user control with a submit/update button. Some or all of these controls are on every page in my application. Depending on where in the application the user is some of the buttons may be disabled. So when a user hits enter the first enabled button on the current page is triggered which results in unpredictable results. I do not want any of the buttons to be triggered by the user hitting enter. The ideal solution if it worked for me would be to use the "Page.RegisterHiddenField("__EVENTTARGET", ButtonName)" method you discuss above. Then I could direct the Enter key to an appropriate button or a hidden button that does nothing. I could use the client side hack you mention above but I would have to do it for every text box on every page in the application and that could get to be cumbersome. Do you have any other suggestions.
Thanks


 
Les Kelly   19 Feb 04 - 12:51 PM

Forgot to include my name in the last comment.

 
Mike   22 Feb 04 - 10:45 PM

Nothing brilliant springs to mind. You appreciate, I hope, that this is an Internet Explorer problem. As such, it's solvable only with some client-script hackery of some sort. The following site suggests a client script that will disable Enter for all controls on the page:

http://www.felgall.com/jstip43.htm

That seems to work for me. If that's too extreme, a not-overly-elegant solution might be to have a Page_Load handler that recursively walks the controls in the page, and if it encounters a TextBox control, it could add the onkeypress script. That would be a semi-automated way to work with the textboxes, anyway.

Other than that, I'm not sure. The __EVENTTARGET trick was actually to make Enter work, not to disable it. :-) As you know, Enter works well -- too well for you -- if you have multiple buttons and/or multiple text boxes on that page.


 
Les Kelly   23 Feb 04 - 7:29 AM

The script in the link you provided is too extreme as I have multi-line text boxes on some of the pages in which the user needs to be able to hit enter for a new line. I guess I'll just stick with my white button method. Thanks for your time and effort.



 
Les Kelly   23 Feb 04 - 7:29 AM

The script in the link you provided is too extreme as I have multi-line text boxes on some of the pages in which the user needs to be able to hit enter for a new line. I guess I'll just stick with my white button method. Thanks for your time and effort.



 
Avinash   06 Aug 04 - 5:45 AM

i tried using the code.

Page.RegisterHiddenField("__EventHandler", "ButtonName");

but it seems that it works only with a single textbox.
i have a page that has two textboxes, two dropdown lists, 2 calenders.
i have a search button which has to be made default.
but with a page of more than a single textbox the code doesnt work.

how do i get across this.
pleaase reply me to my mail id.
that is avinashpp@yahoo.com


 
Anonymous   06 Aug 04 - 5:51 AM


i made a mistake in last mail in the code written.This is the corrected mail.

i tried using the code.

Page.RegisterHiddenField("__EVENTTARGET", "ButtonName");

but it seems that it works only with a single textbox.
i have a page that has two textboxes, two dropdown lists, 2 calenders.
i have a search button which has to be made default.
but with a page of more than a single textbox the code doesnt work.

how do i get across this.
pleaase reply me to my mail id.
that is avinashpp@yahoo.com


 
Azul   14 Jan 05 - 12:11 AM

Hi,

I also have many <asp:Button> (ie. <input type=submit>) in the page, so neither does this "__EVENTTARGET" method work for me.

Instead, I have a stupid but workable solution:
- Copy and paste that button to a most upper-left position
- Set the copied button's width to zero
- in InitializeComponent(), share the same EventHandler with the original button

Then this invisible dummy button will always catch the attention of Enter key.

Azul


 
Sergei Petrov   30 Mar 05 - 7:00 AM

Mike,
have you tried getting this to work with validators? the validation functions seem to get triggered, but nothing actually happens when they validate correctly. (i've gotten around this by disabling client side validation, but that's a kinda goofy side-effect i've noticed)

-Sergei


 
mike   30 Mar 05 - 9:44 AM

I have not tried this with validators. When you say "triggered," do you mean that the validation logic works (server side only, perhaps)?

 
Matt Berther   08 Apr 05 - 9:47 AM

I have a solution [1] that I posted a while back. This solution involves simply adding an invisible HTML textbox to the page.

This works with all validators and so on...

[1] http://www.mattberther.com/2003/06/000125.html


 
Anonymous   07 Jun 05 - 9:34 AM

Excellent, that script is perfect to stop the pesky users!

Thank you!


 
Josh Simerman   13 Jul 05 - 12:03 PM

I got the original method to work, but with a slight change.

Page.RegisterHiddenField("__EVENTTARGET", btnSubmit.UniqueID);

I tried it with btnSubmit.ClientID, and "btnSubmit", and neither of them worked.

The rendered hidden field then looks like this

<input type="hidden" name="__EVENTTARGET" value="PageClassName1:btnSubmit" />


 
tekHedd   02 Sep 05 - 2:38 PM

Sorry too long no comment!
public static void SetDefault(Page page,WebControl theControl,Control defaultButton)
{
theControl.Attributes.Add(
"PostBackEvent",
page.GetPostBackEventReference( defaultButton ) );
}
public static void DisableEnterKey( Page page )
{
string disableScript =
"<script language=\"javascript\" type=\"text/javascript\">\n"
+ "<!--\n"
+ "if(document.addEventListener){\n"
+ "document.addEventListener(\"keypress\", HandleEnterKey, true);\n"
+ "}\n"
+ "else{\n"
+ "document.attachEvent(\"onkeypress\", HandleEnterKey);\n"
+ "} \n"
+ "\n"
+ "// Handle the enter key for a section of a form, binding it to the provided submit buton\n"
+ "function HandleEnterKey(event) {\n"
+ "var nav = window.Event ? true : false;\n"
+ "if (nav) {\n"
+ "return NetscapeEventHandler_KeyDown(event);\n"
+ "} else {\n"
+ "return MicrosoftEventHandler_KeyDown();\n"
+ "}\n"
+ "}\n"
+ "\n"
+ "function NetscapeEventHandler_KeyDown(e) {\n"
+ "if (e.which == 13 && e.target.type != 'textarea' && e.target.type != 'submit') {\n"
+ "e.returnValue = false;\n"
+ "e.cancel = true;\n"
+ "e.preventDefault();\n"
+ "var att = e.target.attributes['PostBackEvent'];\n"
+ "if(att!=null)\n"
+ "eval(att.value)\n"
+ "return false;\n"
+ "}\n"
+ "return true;\n"
+ "}\n"
+ "\n"
+ "function MicrosoftEventHandler_KeyDown() {\n"
+ "if (event.keyCode == 13 && event.srcElement.type != 'textarea' && event.srcElement.type != 'submit') {\n"
+ "event.returnValue = false;\n"
+ "event.cancel = true;\n"
+ "var att = event.srcElement.attributes['PostBackEvent'];\n"
+ "if(att!=null)\n"
+ "eval(att.value)\n"
+ "return false;\n"
+ "}\n"
+ "return true;\n"
+ "}\n"
+ "// -->\n"
+ "</script>\n";
if (! page.IsStartupScriptRegistered("DisableEnterKey"))
{
page.RegisterStartupScript("DisableEnterKey",disableScript);
}
}


 
Matthew Sanders   04 May 06 - 9:00 PM

If you're playing in the wonderful land of Asp.Net 2.0 then consider using the form or panel DefaultButton property.

Visit :

http://harishmvp.blogspot.com/2006/04/aspnet-20-enter-key-default-submit.html

The link says it all.


 
jog   12 Aug 06 - 12:02 AM

I just want to ask how can I enable my text box when a auto post back occur? It has been bothering me for quite sometime now and I have to click outside of the text box to activate it. I will appreciate your most urgent reply on this.

 
mike   12 Aug 06 - 1:14 AM

Jog, I don't understand what you're asking. What is the scenario you have and what happens?

 
Richard   19 Mar 07 - 6:19 AM

Mike,

I'm trying to use the command below on a master page (ASP.NET 2), but it doesn't seem to work.

Page.RegisterHiddenField("__EVENTTARGET", ButtonName.ClientID)

Any suggestions?

Thank you.


 
mike   19 Mar 07 - 8:21 AM

__EVENTTARGET already exists on the page, actually -- it's created for any page that requires JavaScript to perform a postback. Perhaps that's the problem? (If you name it something else, does it work?)

 
Bhushan Karle   01 Jul 07 - 3:08 PM

ASP.NET Panels rock! Along with the Panel's Defaultbutton attribute, I was able to solve my problem! Thank for all the pointers here as well as on HarishMVP's blog!

Problem:
I had a situation where the top of the page had a search term (txtSearchTerm) and a button to search using that term (btnSearch). I wanted this to be the default button. But I also had a button (btnAdvanceSearch) on the same form so which would open up an advance searrch option with multiple search terms and anoter button (btnAdvanceSearchExecute). When using the advance search option, I needed the Enter key to do the click event of btnAdvanceSearchExecute. I would not use the simple methods described here to accomplish both.
Additional complications: my page has a master page (searches are in the child page)

Solution:
I places all the content in my page inside Panel1 for which I placed DeafultButton to be btnSearch. Then I placed all the contents of the Advance Search functionality within a child panel Panel2 for which I set Defaultbutton to be btnAdvanceSearchExecute. The Enter Key correctly recognizes which button click event to be handled.

I can post/email the code if anyone is interested.
Bhushan Karle