Hitting enter after you have typed something in some TextBox control is something natural to most
users, but it
makes life of the ASP.NET developer more difficult. If you don't know about
what I'm talking here is a simple
example. Imagine that you have a simple web form with
two text fields and two button controls. The first text field
and the first button are
used for searching the web site and they are placed somewhere near the top of the page.
The second text field and the second button
are used for some totally different purpose and that's filtering the
entries
displayed on the form.
The important thing to remember is that both buttons, when clicked, are causing postback
and that first button is
rendered before the second button. So, when enter is pressed inside
the first text field, web site will be searched.
So far so good.
But let's suppose that
user has typed something in the second text field. If enter is pressed while
mouse cursor is inside the second text field, user will expect that the form entries will
be filtered. But that isn't going
to happen! The
first button will do the submit and web site will be searched once again.
Described behavior I found in IE7 and Opera. Firefox is immune to this problem. To understand why is
this happening
we need to look at the code. Here is the code of the simple web form which will demonstrate
the problem:
<head runat="server">
...
<script language="javascript" type="text/javascript">
function Submit(id, e) {
var isEnter = window.event == null ?
e.keyCode == 13 :
window.event.keyCode == 13;
if(isEnter)
document.getElementById(id).click();
}
</script>
<script runat="server">
protected void btnSearch_Click(object sender, EventArgs e)
{ lit1.Text = "I'm searching"; }
protected void filterBtn_Click(object sender, EventArgs e)
{ lit1.Text = "I'm filtering"; }
</script>
</head>
<form id="form1" runat="server">
<asp:Literal ID="lit1" runat="server"></asp:Literal>
<br />
<asp:TextBox ID="TextBox1" runat="server"
onkeypress="Submit('btnSearch', event)" />
<asp:Button ID="btnSearch" runat="server"
onclick="btnSearch_Click" Text="Search" />
<br />
<asp:TextBox ID="TextBox2" runat="server"
onkeypress="Submit('filterBtn', event)" />
<asp:Button ID="filterBtn" runat="server"
onclick="filterBtn_Click" Text="Filter" />
</form>
The interesting part isn't the web form source code then the generated html. Here it is only the
important part:
<input name="TextBox1" type="text" id="TextBox1"
onkeypress="Submit('btnSearch', event)" />
<input type="submit" name="btnSearch" value="Search" id="btnSearch" />
<br />
<input name="TextBox2" type="text" id="TextBox2"
onkeypress="Submit('filterBtn', event)" />
<input type="submit" name="filterBtn" value="Filter" id="filterBtn" />
Both buttons are generated as submit buttons and that's what is causing the problems. When you press
enter while you
are typing inside the second text field (TextBox2) default button will do the submit.
Default button, if explicitly not
specified, will be the first rendered button (in this case this is
the btnSearch). You can change the default button by
setting the form's defaultbutton attribute to
id of some other button, but this won't fix the problem. The solution is to say to
ASP.NET
that is shouldn't render
buttons which type is submit. Instead it should render regular buttons. We can do that
with the help of
UseSubmitBehavior property.
All we need to do is to set it to false. The markup will now look like this:
...
<form id="form1" runat="server">
...
<asp:TextBox ID="TextBox1" runat="server"
onkeypress="Submit('btnSearch', event)" />
<asp:Button ID="btnSearch" runat="server" onclick="btnSearch_Click"
Text="Search" UseSubmitBehavior="false" />
<br />
<asp:TextBox ID="TextBox2" runat="server"
onkeypress="Submit('filterBtn', event)" />
<asp:Button ID="filterBtn" runat="server" onclick="filterBtn_Click"
Text="Filter" UseSubmitBehavior="false" />
</form>
Generated HTML now looks like this:
...
<input type="button" name="btnSearch" value="Search" id="btnSearch"
onclick="java_script:__doPostBack('btnSearch','')"/>
...
<input type="button" name="filterBtn" value="Filter" id="filterBtn"
onclick="java_script:__doPostBack('filterBtn','')"/>
That's it. When you press enter inside TextBox1 btnSearch will do the submit, and if you press enter
inside the TextBox2
btnSearch will do the submit.