__doPostBack 仅在页面上有 LinkBut​​ton、Calendar 或 WizardStep 控件时有效

Posted

技术标签:

【中文标题】__doPostBack 仅在页面上有 LinkBut​​ton、Calendar 或 WizardStep 控件时有效【英文标题】:__doPostBack only works if there is a LinkButton, Calendar or WizardStep control on the page 【发布时间】:2016-12-09 13:44:36 【问题描述】:

我发现 __doPostBack 存在问题并找到了解决方法。我正在寻求原因的解释和/或比我的解决方法更好的解决方案。

场景: 我有一个填充了值的下拉列表; “-选择-”、“一”和“二”。如果用户选择“One”,则执行客户端脚本。如果用户选择“Two”,则执行服务器端脚本。

问题: 客户端脚本通过调用 __doPostBack 来启动回发。但是,除非页面上还有 LinkBut​​ton、Calendar 或 WizardStep 控件,否则不会实际发生回发。实际上,我浏览了 Visual Studio 工具箱中的所有标准工具,并对它们进行了全部测试。它必须是这三个之一。

解决方法: 添加一个由 span 包围的链接按钮,显示设置为 none。

<span style="display:none;">
    <asp:LinkButton ID="LinkButton1" runat="server">LinkButton</asp:LinkButton>
</span>

问题:有人可以解释这种行为或提供比我的“解决方法”更好的解决方法吗?

来源 - Javascript(我把它放在头标签之间)

<script language="javascript" type="text/javascript">
    function DropDownList1_change(elementRef) 
        var selectedIndex = elementRef.selectedIndex;
        if (selectedIndex > 0) 
            var selectedValue = elementRef.options[selectedIndex].value;
            if (selectedValue == "One") 
                alert("Because you selected 'One', special javascript code will be executed");
                // Special javascript code goes here
                return;
            
            else if (selectedValue == "Two") 
                // Special server code gets executed on server DropDownList1_SelectedIndexChanged
                __doPostBack('DropDownList1', '');
            
        
    
</script>

来源 - ASPX 控件

    <asp:DropDownList ID="DropDownList1" runat="server"  onchange="DropDownList1_change(this)" OnSelectedIndexChanged="DropDownList1_SelectedIndexChanged">
        <asp:ListItem>-Select-</asp:ListItem>
        <asp:ListItem>One</asp:ListItem>
        <asp:ListItem>Two</asp:ListItem>
    </asp:DropDownList>
    <br />

    <!-- For some unknown reason __doPostBack only works if there is a LinkButton, Calendar or WizardStep control on the page -->      
    <span style="display:none;">
        <asp:LinkButton ID="LinkButton1" runat="server">LinkButton</asp:LinkButton>
    </span>

    Time of last Post Back: <asp:Label ID="Label1" runat="server"></asp:Label><br />
    Time of OnSelectedIndexChanged: <asp:Label ID="Label2" runat="server"></asp:Label>

来源 - 背后的代码

    protected void Page_Load(object sender, EventArgs e)
    
        Label1.Text = DateTime.Now.ToLongTimeString();
    

    protected void DropDownList1_SelectedIndexChanged(object sender, EventArgs e)
    
        Label2.Text = DateTime.Now.ToLongTimeString();
    

其他资源 - 我在发布此问题后发现了以下文章。这是一篇非常古老的 Microsoft 文章,也是我发现的唯一一篇提到 DropDowns、返回值和回发的具体限制的 Microsoft 文章。我还没有深入研究他们的解决方案,也不确定时间是否允许我这样做。主要是在我的解决方案失败或对其他人不起作用的情况下发布它。

直觉上,您可能会认为为 DropDownList 与为 Button Web 添加此类对话框相同 控制。也就是简单的设置 DropDownList 的客户端 onchange 属性类似于:return confirm(...);.使用: DropDownListID.Attributes("onchange") = "return confirm(...);" 不幸的是,这不会按预期工作,因为 AutoPostBack DropDownList 的 onchange 属性将设置为一点 JavaScript 导致回发,即调用客户端 __doPostBack 功能。以编程方式设置 onchange 属性时 你自己,最终结果是呈现的客户端 onchange 事件处理程序既有您的代码,也有对 __doPostBack 的调用:

文章较长,请搜索“Confirmation with AutoPostBack DropDownLists”

https://msdn.microsoft.com/en-us/library/aa479302.aspx

【问题讨论】:

老实说,我最好的解决方法是不使用 WebForms。对于在浏览器中做任何自定义的事情,比如你正在做的事情,这项技术绝对是糟糕的。如果您使用 WebForms,那么在我看来,您应该 100% 使用它,这意味着不要使用 onchange 并执行传统的 javascript,而是在回发本身内部处理您的 One 场景,并可能在响应中注册自定义 javascript回发。 您在新项目中观察到这种行为吗?我尝试重现问题(使用 VS 2010 和 .NET Framework 4.0)并且每次都通过在 DropDownList 中选择一个项目来执行回发。 我在一个新项目中得到了同样的行为;我创建了一个空的新网站和 Web 应用程序项目来测试它。我正在使用 VS 2010、.NET Framework 4、windows 7 32 位和 Cassini(将从 IIS 中尝试)。 试过 IIS 而不是 Cassini。同样的问题。 __doPostBack 不应该被客户端脚本直接使用。这就是为什么它有双下划线。像私人私人一样。 【参考方案1】:

有两种解决方案。

解决方案 1: 比添加被隐藏的 span 标签包围的链接按钮更好的work around 是将以下内容添加到页面加载事件中。这确保函数 __doPostBack 可用。

protected void Page_Load(object sender, EventArgs e)

    Page.ClientScript.GetPostBackEventReference(this, string.Empty);

函数__doPostBack 仅在表单中的控件需要它执行回发时生成。这包括 LinkBut​​ton 等控件和其他将AutoPostBack 设置为true 的控件。事实上,只有 Button 和 ImageButton 控件可以在没有__doPostBack 的情况下执行回发(请参阅this article)。例如,我们可以在 html 输出中看到 LinkBut​​ton 是以这种方式呈现的:

<a id="lnk" href="javascript:__doPostBack(&#39;lnk&#39;,&#39;&#39;)">My link</a>


解决方案 2: 以下方法在不使用 __doPostBack 的情况下实现了相同的目的。

在本例中,您可以为 DropDownList 设置 AutoPostBack="true"

<asp:DropDownList AutoPostBack="true" onchange="if (!confirmPostBack(this)) return false;" ... >

当您想要阻止回发时,onchange 事件处理程序将返回 false。 Javascript 函数可能是这样的:

function confirmPostBack(ddl)

    if (condition) 
        ...
        return true;
     
    else 
        ...
        return false;
    

重要提示onchange 事件处理程序不应返回任何内容以允许回发发生。您可以使用以下语法:

onchange="if (!confirmPostBack(this)) return false;"

由于问题中提到的文章中可能解释的原因,以下语法不起作用。返回true 仍然会阻止回发。

onchange="return confirmPostBack(this);" // Does not work!

【讨论】:

这就是我第一次尝试的方式。但是,返回 true/false 不适用于由下拉菜单启动的 javascript。单击按钮后,可以使用 return false 取消回发,但是,不能使用下拉菜单。这是一个鲜为人知的下拉限制。互联网上有一些解决方法。请不要打扰发布任何我已经尝试过的原因。我真的只是想了解为什么我需要添加一个 LinkBut​​ton 来使 __doPostBack 工作。 你说不行。但它确实有效。测试 100%。重要的是,如果您希望回发发生,请不要返回任何内容,甚至不要返回 true 我不明白你所说的不返回任何东西是什么意思。您编写的 confirmPostBack 函数返回 true 或 false。 答案末尾见我的注释。正如您所说,confirmPostBack 返回truefalse,但onchange 事件处理程序不会返回任何内容,如果它是true。另请注意,我在页面中添加了对__doPostBack 存在(或不存在)的解释。 我添加了一个解决方法,确保在呈现的页面中生成__doPostBack

以上是关于__doPostBack 仅在页面上有 LinkBut​​ton、Calendar 或 WizardStep 控件时有效的主要内容,如果未能解决你的问题,请参考以下文章

__doPostBack 未定义

Python - 发送 __doPostBack(加入 Roblox 中的群组)

__doPostBack() 是不是有可能发送 GET 请求?

IE10 SCRIPT5009:“__doPostBack”未定义

_doPostBack用法总结

__doPostBack 方法解析