ASP.NET GridView Image Command Button 问题(多次回发)






4.48/5 (16投票s)
本文描述了在使用 ASP.NET GridView 中的 Image 类型命令按钮时(Internet Explorer 浏览器下)出现多次回发问题的解决方法。
最后更新:2008-10-10 更新了模板解决方案
要运行该应用程序,请将其下载并解压到计算机上的一个文件夹中,然后用 Visual Studio 2005(专业版或 Web 版)打开,并通过开发服务器运行。

引言
我遇到了一个问题:在 GridView 中通过点击 Type 为 Image 的 CommandField 来选择一行后,页面会加载两次。我发现客户端发送了两个请求:第一个请求不是我页面上的 PostBack 请求(这是我没想到的请求);第二个请求是我页面上的 PostBack 请求(这是我期望的请求)。
如果有什么非常奇怪的事情,我总是会用 FireFox 来检查,果然不出所料,只有一个请求(预期的 PostBack 请求)。因此,我也用 Internet Explorer 6 进行了检查,问题出现的概率大约是 4 次中有 1 次?!?
总结一下:
- Internet Explorer 7:始终 2 个请求
- Internet Explorer 6:有时正常,有时不正常
- FireFox:一切正常
注意:这种行为仅在使用 CommandField 的 Type 为 Image 时出现,如果是 Link 或 Button 类型,一切都运行良好。
如果一切正常,我会如何处理?
以下 ASPX 定义显示了一个带有 Image 类型 CommandButton 的 GridView。
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False"
DataSourceID="ObjectDataSource1"
OnSelectedIndexChanged="SelectedIndexChanged">
<Columns>
<asp:CommandField ButtonType="Image"
SelectImageUrl="~/Select.gif" ShowSelectButton="True" />
<asp:BoundField DataField="A" HeaderText="A" SortExpression="A" />
<asp:BoundField DataField="B" HeaderText="B" SortExpression="B" />
<asp:BoundField DataField="C" HeaderText="C" SortExpression="C" />
</Columns>
</asp:GridView>
这个 GridView 会导致我在引言中描述的问题。尽管我真的不明白哪里出了错,但它就是不起作用。如果您比较具有 Link 类型 CommandButton 的 GridView 和具有 Image 类型 CommandButton 的 GridView 所生成的 HTML,您会发现它们之间并没有太大区别——除了前者只有一个请求而后者有两个!
我花了一些时间在 Google 上搜索,发现了一些解决方法。我将找到的所有信息汇集起来,并在接下来的几节中向您展示三个解决方法,以及它们的优缺点。
解决方案 1 - 使用 Link 类型的 CommandButton,并将图像作为 HTML 添加到链接文本中
这是最简单的解决方法。我只是将 CommandButton 的类型从 Image 改为 Link,并将其 Text 属性设置为显示图像的 HTML。
<asp:GridView ID="GridView2" runat="server" AutoGenerateColumns="False"
DataSourceID="ObjectDataSource1">
<Columns>
<asp:CommandField ShowSelectButton="True"
SelectText="<img src='Select.gif' border=0 title='This is a Tooltip'>">
</asp:CommandField>
<asp:BoundField DataField="A" HeaderText="A" SortExpression="A" />
<asp:BoundField DataField="B" HeaderText="B" SortExpression="B" />
<asp:BoundField DataField="C" HeaderText="C" SortExpression="C" />
</Columns>
</asp:GridView>
这样做效果很好,但有一个缺点:工具提示文本的本地化变得困难。整个 HTML 字符串都必须添加到本地资源中,这不太方便。
解决方案 2 - 切换到 TemplateFields
为了获得更好的本地化解决方案,我删除了 CommandField 列,并添加了一个包含 ImageButton 的模板列。为了获得相同的行为,CommandName 必须设置为“Select”。
<asp:GridView ID="GridView3" runat="server" AutoGenerateColumns="False"
DataSourceID="ObjectDataSource1">
<Columns>
<asp:TemplateField ShowHeader="false">
<ItemStyle HorizontalAlign="Center" />
<ItemTemplate>
<asp:ImageButton ID="btnView" runat="server"
CausesValidation="False" CommandName="Select"
ImageUrl="~/Select.gif" ToolTip="View" />
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField DataField="A" HeaderText="A" SortExpression="A" />
<asp:BoundField DataField="B" HeaderText="B" SortExpression="B" />
<asp:BoundField DataField="C" HeaderText="C" SortExpression="C" />
</Columns>
</asp:GridView>
自定义命令示例
为了让您的自定义命令正常工作,您可以选择使用 ButtonField,将其 ButtonType 设置为 Link,并使用与解决方案 1 中相同的技巧来显示图像,或者使用解决方案 2 中的模板字段。我更倾向于解决方案 2,但请确保在定义中包含 CommandArgument,否则您将无法访问行索引。
以下示例显示了这一点,以及不起作用的方法(请参阅工具提示以了解发生了什么)。
<asp:GridView ID="GridView4" runat="server" AutoGenerateColumns="False"
DataSourceID="ObjectDataSource1" OnRowCommand="RowCommand">
<Columns>
<asp:ButtonField ButtonType="Image" CommandName="MyCommand1"
ImageUrl="~/Select.gif"
Text="Double PostBack in IE7 (sometimes in IE6)" />
<asp:TemplateField ShowHeader="False">
<ItemStyle HorizontalAlign="Center" />
<ItemTemplate>
<asp:ImageButton ID="btnView" runat="server" CausesValidation="False"
CommandName="MyCommand2"
CommandArgument="<%# Container.DataItemIndex %>"
ImageUrl="~/Select.gif"
ToolTip="Works! Preferred solution." />
</ItemTemplate>
</asp:TemplateField>
<asp:ButtonField ButtonType="Link" CommandName="MyCommand3"
Text="<img src='Select.gif' border=0 title='Works! But bad localizable.'>"
/>
<asp:BoundField DataField="A" HeaderText="A" SortExpression="A" />
<asp:BoundField DataField="B" HeaderText="B" SortExpression="B" />
<asp:BoundField DataField="C" HeaderText="C" SortExpression="C" />
</Columns>
</asp:GridView>
结论
Internet Explorer 中存在一个问题,在使用 Image 类型的 CommandButton 时会导致多次 PostBack。只要这个 bug 没有修复(或者每个人都使用 FireFox ;-)), 我们就必须使用一些解决方法。在本文中,我向您展示了三个解决方法以及您可以使用它们的场景。简而言之:如果您使用模板字段,您将始终是安全的。
如果您有更多信息、其他/更好的解决方法,甚至真正的解决方案,请在下方发布!
历史
- 2007-08-09 初始版本
- 2008-10-10 根据 Petr Behensky 在其消息帖子中的建议,更改了模板字段解决方案