在同一时间内,OnclientClick和OnClick无法同时起作用吗?

56
我有一个如下的按钮:
<asp:Button ID="pagerLeftButton" runat="server" OnClientClick="disable(this)" onclick="pager_Left_Click" Text="<" />

当我使用这个按钮时,如果加上OnClientClick属性,onclick事件就不会被触发。但是如果我去掉OnClientClick属性,那么onclick事件就能被触发。

我需要做的是,在postback期间禁用按钮,在postback结束后启用它。

编辑:附加信息:

我在C#部分的触发函数中添加了断点并进行了调试,它们肯定没有触发。这些函数类似于

protected void pager_Left_Click(object sender, EventArgs e)
{
//Do smthing.
}
protected void pager_Right_Click(object sender, EventArgs e)
{
//Do smthing.
}

当我点击这个按钮时,它会在1-2秒内被禁用并自动启用,但我不确定为什么它会重新启用。我没有添加任何部分使其重新启用。


1
你能展示一下你的“disable”函数吗? - SLaks
1
你能发布你的disable() Javascript方法吗? - Mike Cole
禁用JavaScript函数是什么样子的?当你调用disable(this)时...我假设它是常见的,但想要确认一下。 - curtisk
1
函数禁用(控件) { 控件.disabled =“disabled”; 警告(100); } - stckvrflw
7个回答

104

从这篇网页存档文章得知:

关键是使用按钮控件的OnClientClick和UseSubmitBehavior属性。虽然还有其他方法,涉及到在服务器端添加属性的代码,但我认为这种方式的简单性更加吸引人:

<asp:Button runat="server" ID="BtnSubmit"  OnClientClick="this.disabled = true; this.value = 'Submitting...';"   UseSubmitBehavior="false"  OnClick="BtnSubmit_Click"  Text="Submit Me!" />

OnClientClick 允许在客户端添加 OnClick 脚本。在这种情况下,JavaScript 将禁用按钮元素并将其文本值更改为进度消息。当后台回发完成时,新呈现的页面将自动将按钮恢复到初始状态,而无需进行任何额外的工作。

在客户端禁用提交按钮的一个缺点是它会取消浏览器的提交,从而取消后台回发。将 UseSubmitBehavior 属性设置为 false 告诉.NET注入必要的客户端脚本来触发后台回发,而不是依赖于浏览器的表单提交行为。在这种情况下,注入的代码将是:

__doPostBack('BtnSubmit','')

在我们的OnClientClick代码末尾添加了这个,使我们得到了这个渲染后的HTML:

<input type="button" name="BtnSubmit"  onclick="this.disabled = true; this.value ='Submitting...';__doPostBack('BtnSubmit','')"  value="Submit Me!" id="BtnSubmit" />

这提供了一个很好的按钮禁用效果和处理文本,同时后台完成。


6
这是正确答案。你应该编辑你的答案以包含文章中的信息。(UseSubmitBehavior="false" - SLaks
@Sam,我的回答是链接到文章的,但其他人在SO上要求我包含内容。不管怎样,我已经包含了链接。谢谢。 - Vinay Pandey
@VinayPandey,不客气!我仍然认为你的回答格式不够清晰,无法明确表明你在引用别人的话。我已经建议对答案进行编辑,以便向您展示我的意思。 - Sam
1
这种方法的缺点是当JavaScript被禁用或不可用时,按钮将不再起作用。 - Sam
在我看来,对于VB.NET,您不需要设置OnClick事件,因为您在代码后台中的事件处理程序子程序上有Handles关键字。 - John
显示剩余5条评论

16

在使用OnClientClick和OnClick时,似乎非常挑剔。

我尝试了以下用例但没有成功:

OnClientClick="return ValidateSearch();" 
OnClientClick="if(ValidateSearch()) return true;"
OnClientClick="ValidateSearch();"

但是它们没有起作用。以下内容起作用:

<asp:Button ID="keywordSearch" runat="server" Text="Search" TabIndex="1" 
  OnClick="keywordSearch_Click" 
  OnClientClick="if (!ValidateSearch()) { return false;};" />

这会产生 SyntaxError: Unexpected token if。那前面不应该有一个 javascript 协议吗? - crthompson
运行良好。谢谢! JS函数应该在成功验证后返回true,否则OnClick将不会被触发。 - Aki
一个简单、美观且可行的解决方案,专为“Webforms”新手而设计 :) 感谢Garry。 - Zeeshan
1
这真是太奇怪了,但它确实有效。谢谢! - Mmm
我也不确定为什么这个语法相比之前的能够工作,但这也帮助了我。 - jmai

8
这里有两个问题:
禁用客户端按钮会阻止postback
为了解决这个问题,在JavaScript onclick事件之后,禁用按钮。可以使用setTimeout来轻松实现,就像这个答案中建议的那样。
此外,即使ASP.NET验证失败,OnClientClick代码也会运行,因此最好添加一个检查Page_IsValid的条件语句。这确保在验证失败时不会禁用按钮。
OnClientClick="(function(button) { setTimeout(function () { if (Page_IsValid) button.disabled = true; }, 0); })(this);"

如问题所示,将所有 JavaScript 代码放在自己的函数中更加整洁:

OnClientClick="disable(this);"

function disable(button) {
    setTimeout(function () {
        if (Page_IsValid)
            button.disabled = true;
    }, 0);
}

在客户端禁用按钮并不会在服务器端禁用它

为了解决这个问题,应该在服务器端禁用按钮。例如,在OnClick事件处理程序中:

OnClick="Button1_Click"

protected void Button1_Click(object sender, EventArgs e)
{
    ((Button)sender).Enabled = false;
}

最后,请记住,防止重复按钮按下并不能防止两个不同的用户在同时提交相同的数据。请确保在服务器端考虑到这一点。

10
请投反对票的人告诉我问题出在哪里?如果我错了,我想知道,这样我就可以删除这个回答并从错误中学习。或者,如果你只是不理解我的代码或背后的推理,请提问。在后一种情况下,你通过对好的建议投反对票对社区造成了伤害。 - Sam
这是关于根本原因和背后有用的解决方法的最佳解释。 - DanO

6
Vinay(上面的人)提供了一个有效的解决方法。 实际导致按钮的OnClick事件在OnClientClick事件函数后无法运行的原因是因为MS定义了一旦按钮被禁用(在OnClientClick事件调用的函数中),按钮将“尊重”此操作,不会调用OnClick事件定义的方法来完成按钮的操作。
我花了几个小时来努力弄清楚这一点。一旦我删除了禁用提交按钮的语句(位于OnClientClick函数内部),OnClick方法就可以被调用,而没有进一步的问题。 如果你在听,请注意,Microsoft:一旦按钮被点击,它应该完成它分配的活动,即使它在进行此活动的过程中被禁用。只要它被单击时没有被禁用,它就应该完成所有分配的方法。

在这里,在这里!微软,遵循标准,该死的! - Pastor Bones

2
如果你不立即将按钮设置为禁用,而是通过setTimeout延迟该操作,会怎么样呢? 你的“禁用”函数会返回并且提交将继续进行。

1

你的 JavaScript 很好,除非在此页面上运行其他脚本可能会破坏一切。您可以使用 Firebug 进行检查。

我现在已经进行了一些测试,似乎 ASP.net 忽略了禁用的控件。基本上,发生了回发,但可能框架忽略了这样的事件,因为它“假定”禁用的按钮不能引发任何回发,因此它忽略了可能附加的处理程序。现在这只是我的个人推理,可以使用 Reflector 更深入地检查这一点。

作为解决方案,您可以尝试在稍后的时间点禁用控件,基本上您可以使用 JavaTimer 或其他功能延迟 control.disabled = "disabled" 调用。通过这种方式,首先向服务器发出回发,然后再由 JavaScript 函数禁用控件。没有测试过,但可能有效。


0

函数 UpdateClick(btn) {

    for (i = 0; i < Page_Validators.length; i++) {

        ValidatorValidate(Page_Validators[i]);

        if (Page_Validators[i].isvalid == false)

            return false;
    }

    btn.disabled = 'false';

    btn.value = 'Please Wait...';

    return true;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接