Использование свойства Panel.DefaultButton с контролом LinkButton в ASP.NET

Aug 25
2007 12:53 (ASP.NET, Программирование) · English (12,896 views)

В ASP.NET есть существенное ограничение — на странице может быть только одна серверная форма. Даже если вы разрабатываете сложную страницу, которая выглядит как несколько форм с разными submit-кнопками, в действительности у вас есть только одна форма. Возникает следующая проблема: как браузер понимает, какая кнопка должна сработать, когда пользователь нажимает ENTER? Он использует первый контрол Button (что обычно неверно), а если вы используете LinkButton‘ы, они вообще не сработают. В ASP.NET 2.0 было добавлено новое свойство контролам Panel и HtmlFormDefaultButton, которое используется для указания ID контрола, реализующего интерфейс IButtonControl (обычно Button и LinkButton). Этот контрол сработает, когда пользователь нажмет ENTER. Но существует одна большая проблема: контрол LinkButton не сработает в Firefox по нажатию ENTER. В этой статье я покажу, почему возникает проблема и предложу ее решение.

Рассмотрим, как работает DefaultButton в ASP.NET. Вот простой пример:

<asp:Label runat="server" ID="lblHello" />
<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>
protected void lbHello_Click(object sender, EventArgs e)
{
    lblHello.Text = String.Format("Hello, {0}", txtFirstName.Text);
}

Когда вы попытаетесь нажать кнопку ENTER в поле ввода, форма будет отправлена на сервер, но событие Click контрола LinkButton не сработает. Давайте укажем свойство DefaultButton панели.

<asp:Panel runat="server" DefaultButton="lbHello">
    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 onkeypress="javascript:return WebForm_FireDefaultButton(event, 'lbHello')">
</div>

Вот метод WebForm_FireDefaultButton, определенный в библиотеке JavaScript ASP.NET:

function WebForm_FireDefaultButton(event, target) {
    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:

var b = document.getElementById('<%= lbHello.ClientID %>');
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;
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 файл:

<%@ Register Namespace="App_Code" TagPrefix="ac" %>
<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.

Надеюсь, заметка поможет вам. Комментарии приветствуются.

13 отзывов на 'Использование свойства Panel.DefaultButton с контролом LinkButton в ASP.NET'

Подписаться на комментарии по RSS или TrackBack на 'Использование свойства Panel.DefaultButton с контролом LinkButton в ASP.NET'.

1
parthiban
сказал 06.09.2007 в 13.42

asp.net panel scroll bars not visible in opera.why?

2
сказал 19.09.2007 в 16.25

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

3
сказал 19.09.2007 в 16.47

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:Button runat="server" ID="btnSubmit" Text="submit" />
<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.

4
Tyler Thompson
сказал 27.09.2007 в 19.52

That worked perfectly! Thank you for your post.

5
сказал 25.10.2007 в 20.45

[...] 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 [...]

6
сказал 14.11.2007 в 7.39

[...] 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... [...]

7
сказал 12.12.2007 в 23.27

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.

8
Тимур
сказал 15.02.2008 в 8.53

Работает идеально, спасибо! Но… Очень бы хотелось, чтобы работало в опере по Ctrl + Enter (автозаполнение). Есть идеи?
Спасибо.

9
Chris
сказал 23.02.2008 в 5.49

Dave’s solution is the way to go.

10
uttam
сказал 10.03.2008 в 15.43

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—————————

function clickButton(e,buttonid) {
    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

txtUserName.Attributes.Add("onkeypress", "javascript:return clickButton(event,'" + btnSearch.ClientID + "');");
11
uttam
сказал 10.03.2008 в 15.50

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

12
Jared Holgate
сказал 21.04.2008 в 13.16

This solution worked perfectly. Thank you very much.

13
Martin
сказал 22.04.2008 в 14.38

Solution is ok. Unfortunatelly, this does not work under Firefox 3.

Anyone know how to do it?

Оставить отзыв

Вы можете использовать простые теги форматирования HTML (вроде <a>, <ul> and others). Чтобы вставить пример код, используйте <code lang="php">$a = "hello";</code> (поддерживаемые языки: ruby, php, yaml, html, csharp, javascript). Также Вы можете использовать <code>$a = "hello";</code>, синтаксис не будет подсвечен. Если вы не хотите использовать тег <code>, замените символ < на &lt;.

Отправить

 
Copyright © 2005 - 2008, Dmytro Shteflyuk