__doPostBack 仅在页面上有 LinkButton、Calendar 或 WizardStep 控件时有效
Posted
技术标签:
【中文标题】__doPostBack 仅在页面上有 LinkButton、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 来启动回发。但是,除非页面上还有 LinkButton、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
仅在表单中的控件需要它执行回发时生成。这包括 LinkButton 等控件和其他将AutoPostBack
设置为true
的控件。事实上,只有 Button 和 ImageButton 控件可以在没有__doPostBack
的情况下执行回发(请参阅this article)。例如,我们可以在 html 输出中看到 LinkButton 是以这种方式呈现的:
<a id="lnk" href="javascript:__doPostBack('lnk','')">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 取消回发,但是,不能使用下拉菜单。这是一个鲜为人知的下拉限制。互联网上有一些解决方法。请不要打扰发布任何我已经尝试过的原因。我真的只是想了解为什么我需要添加一个 LinkButton 来使 __doPostBack 工作。 你说不行。但它确实有效。测试 100%。重要的是,如果您希望回发发生,请不要返回任何内容,甚至不要返回true
。
我不明白你所说的不返回任何东西是什么意思。您编写的 confirmPostBack 函数返回 true 或 false。
答案末尾见我的注释。正如您所说,confirmPostBack
返回true
或false
,但onchange
事件处理程序不会返回任何内容,如果它是true
。另请注意,我在页面中添加了对__doPostBack
存在(或不存在)的解释。
我添加了一个解决方法,确保在呈现的页面中生成__doPostBack
。以上是关于__doPostBack 仅在页面上有 LinkButton、Calendar 或 WizardStep 控件时有效的主要内容,如果未能解决你的问题,请参考以下文章
Python - 发送 __doPostBack(加入 Roblox 中的群组)
__doPostBack() 是不是有可能发送 GET 请求?