В ASP.NET есть существенное ограничение — на странице может быть только одна серверная форма. Даже если вы разрабатываете сложную страницу, которая выглядит как несколько форм с разными submit-кнопками, в действительности у вас есть только одна форма. Возникает следующая проблема: как браузер понимает, какая кнопка должна сработать, когда пользователь нажимает ENTER? Он использует первый контрол Button (что обычно неверно), а если вы используете LinkButton‘ы, они вообще не сработают. В ASP.NET 2.0 было добавлено новое свойство контролам Panel и HtmlForm — DefaultButton, которое используется для указания ID контрола, реализующего интерфейс IButtonControl (обычно Button и LinkButton). Этот контрол сработает, когда пользователь нажмет ENTER. Но существует одна большая проблема: контрол LinkButton не сработает в Firefox по нажатию ENTER. В этой статье я покажу, почему возникает проблема и предложу ее решение.
Рассмотрим, как работает DefaultButton в ASP.NET. Вот простой пример:
<asp:Panel runat="server">
First name: <asp:TextBox runat="server" ID="txtFirstName" />
<asp:LinkButton ID="lbHello" runat="server" Text="Click me" OnClick="lbHello_Click" />
</asp:Panel>
{
lblHello.Text = String.Format("Hello, {0}", txtFirstName.Text);
}
Когда вы попытаетесь нажать кнопку ENTER в поле ввода, форма будет отправлена на сервер, но событие Click контрола LinkButton не сработает. Давайте укажем свойство DefaultButton панели.
First name: <asp:TextBox runat="server" ID="txtFirstName" />
<asp:LinkButton ID="lbHello" runat="server" Text="Click me" OnClick="lbHello_Click" />
</asp:Panel>
Отлично! Идеально работает в Internet Explorer, но как насчет Firefox? Упс, у нас проблема. Вы можете найти решение в конце заметки, но сначала я хотел бы показать, почему возникает эта проблема. Когда вы указываете свойство DefaultButton, ASP.NET генерирует следующий код:
</div>
Вот метод WebForm_FireDefaultButton, определенный в библиотеке JavaScript ASP.NET:
if (event.keyCode == 13 && !(event.srcElement && (event.srcElement.tagName.toLowerCase() == "textarea"))) {
var defaultButton;
if (__nonMSDOMBrowser) {
defaultButton = document.getElementById(target);
}
else {
defaultButton = document.all[target];
}
if (defaultButton && typeof(defaultButton.click) != "undefined") {
defaultButton.click();
event.cancelBubble = true;
if (event.stopPropagation) event.stopPropagation();
return false;
}
}
return true;
}
Проблема возникает в коде typeof(defaultButton.click) != “undefined” — Firefox не определяет метод click() для элемента a, поэтому форма будет отправлена на сервер без параметра __EVENTTARGET, и событие не сработает. Простейшее решение — определить метод click() для a:
if (b && typeof(b.click) == 'undefined') {
b.click = function() {
var result = true;
if (b.onclick) result = b.onclick();
if (typeof(result) == 'undefined' || result) {
eval(b.href);
}
}
}
Наш метод click() имитирует поведение элемента a: сначала он вызывает метод onclick() (атрибут OnClientClick контрола LinkButton), и если тот возвращает false — прекращает обработку. Затем он делает eval атрибуту href (где ASP.NET размещает вызов __doPostBack).
Давайте создадим свой контрол, который инкапсулирует эту логику:
using System.Web.UI.WebControls;
namespace App_Code
{
public class LinkButtonDefault : LinkButton
{
protected override void OnLoad(System.EventArgs e)
{
Page.ClientScript.RegisterStartupScript(GetType(), "addClickFunctionScript",
_addClickFunctionScript, true);
string script = String.Format(_addClickScript, ClientID);
Page.ClientScript.RegisterStartupScript(GetType(), "click_" + ClientID,
script, true);
base.OnLoad(e);
}
private const string _addClickScript = "addClickFunction('{0}');";
private const string _addClickFunctionScript =
@" function addClickFunction(id) {{
var b = document.getElementById(id);
if (b && typeof(b.click) == 'undefined') b.click = function() {{
var result = true; if (b.onclick) result = b.onclick();
if (typeof(result) == 'undefined' || result) {{ eval(b.href); }}
}}}};";
}
}
И соответствующий .aspx файл:
<asp:Label runat="server" ID="lblHello" />
<asp:Panel runat="server" DefaultButton="lbHello">
First name: <asp:TextBox runat="server" ID="txtFirstName" />
<ac:LinkButtonDefault ID="lbHello" runat="server" Text="Click me" OnClick="lbHello_Click" />
</asp:Panel>
Безусловно, код JavaScript должен быть вынесен из кода C#, но для моего примера этого достаточно. Если вы используете библиотеку ASP.NET AJAX, вы должны вызывать метод ScriptManager.RegisterStartupScript вместо ClientScriptManager.RegisterStartupScript.
Надеюсь, заметка поможет вам. Комментарии приветствуются.
Русский
English
asp.net panel scroll bars not visible in opera.why?
hi
I am using Aspnet ajax in my application, i used asp button for submiting a form, beacuse asp:Button work in both condition when Javascript is enable or disabled.
but asp:button are not look good in mac broswer so client do want asp:Button/asp:ImageButton in whole application.
Please advise What would be the replcaement of asp:Button/asp:ImageButton which will work in both condition when Javascript is enable or disabled.
Thanks
Regards
Raghvendra
to_raghvendra@yahoo.com
asp:LinkButton works only when JavaScript is enabled, you right. I see only one solution: add two buttons at the same time (for browsers that does not support JavaScript — asp:Button, visible by default, and asp:LinkButton for ones, that support JavaScript), and switch their visibility using JavaScript. Something like this:
<asp:LinkButton runat="server" ID="lbSubmit" style="display:none" Text="submit" />
<script type="text/javascript">
document.getElementById("<%= btnSubmit.ClientID %>").style.display = 'none';
document.getElementById("<%= lbSubmit.ClientID %>").style.display = '';
</script>
But of course this is not perfect solution. BTW, you could use images as background of the asp:Button or asp:ImageButton, and they would look perfectly in Safari.
That worked perfectly! Thank you for your post.
[...] is one solution that creates their own “click” event for the LinkButton. You can look at it here (this solution does work as well, i just found it too much). I wanted something simpler, Simple is [...]
[...] But of course if you are using a LinkButton, then its a whole another ball game. None of the techniques described above might work for you. But you are in luck, this page has what you need to get around that — http://kpumuk.info/asp-net/using-panel... [...]
One simple way to get around the Linkbutton issue and the firefox issue is to set up a “shadow” button on the page with a style="display:none;"
So, say I have a login form, I will put a link button on the form in case the user is going to click it directly. Then, just underneath it I will add a hidden asp:Button, with display:none, and tie that to the same event as the regular login linkbutton.
Works in both IE7 and FF2 as far as I can tell, and doesn’t require any javascript — just a stupid workaround.
Работает идеально, спасибо! Но… Очень бы хотелось, чтобы работало в опере по Ctrl + Enter (автозаполнение). Есть идеи?
Спасибо.
Dave’s solution is the way to go.
Hi guys i found solution finally.
Setting link button as Default button for FIREFOX as well as IE:
use this fallowing code–>
in .aspx file—————————
debugger;
var bt = document.getElementById(buttonid);
if (typeof(bt) == 'object') {
if (navigator.appName.indexOf("Netscape") > -1) {
if(e.keyCode == 13) {
if (bt && typeof(bt.click) == 'undefined') {
bt.click = addClickFunction1(bt);
}
}
}
if (navigator.appName.indexOf("Microsoft Internet Explorer") > -1) {
if (event.keyCode == 13) {
bt.click();
return false;
}
}
}
}
function addClickFunction1(bt) {
debugger;
var result = true;
if (bt.onclick) result = bt.onclick();
if (typeof(result) == 'undefined' || result) {
eval(bt.href);
}
}
————————-
in aspx.cs file (write code for the text boxes u required)
aspx.cs file(C#.net code)—>
in Page_Load Event
reg Above Code–>
Please read this for the reference of the above code , and read the ID’s for the textbox’s and Link Buttons
for the above code in aspx form ,we have
a
asp Text box with id “txtUserName”
and
a
link button with id “btnSearch”
like
This solution worked perfectly. Thank you very much.
Solution is ok. Unfortunatelly, this does not work under Firefox 3.
Anyone know how to do it?