Last update: 2008-10-10 Updated template solution
To run the application, download and unzip it to a folder on your computer and open it with Visual Studio 2005 (Pro or Web Edition) and run it over the development server.
Introduction
I ran into the problem that my page was loaded twice after selecting a row in a GridView
by clicking on a CommandField
with Type
equal to Image
. I found out that two requests were sent from the client: the first request is not a PostBack
request on my page (this is the request I didn't expect; the second request is a PostBack
request on my page (this is the request I expected).
If something is completely strange, then I always check it in FireFox and to no much surprise, there is only one request (the expected PostBack
request). Therefore I also checked it with Internet Explorer 6 and there the problem occurs once in about 4 times!?!?
To sum it up:
- Internet Explorer 7: Always 2 requests
- Internet Explorer 6: Sometimes it's okay, sometimes not
- FireFox: Everything works correctly
Note: This behaviour is only present when using Image
as type
of the CommandField
, with Link
or Button
, everything works great.
How I Would Do It When Everything Would Be Correct
The following ASPX definition shows a GridView
with a CommandButton
of type image
:
<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>
This GridView
results in the problems I described in the introduction. Although, I really don't understand what could go wrong here, it simply doesn't work. If you compare the generated HTML for a GridView
with a CommandButton
of type Link
and one of type Image
, then you'll see that nothing is really different - except that once there will be only one request and once there will be two!
I spent some time Googling and found some workarounds. I assembled all the information that I found and show you in the following sections three workarounds along with their advantages and disadvantages.
Solution 1 - Use CommandButton of Type Link and Add the Image as HTML in the Link Text
This is the simplest workaround. I simply change the type of the CommandButton
to be Link
instead of Image
and set the Text
property to some HTML that will show the image:
<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>
This works great but has one disadvantage: the localization of the tooltip text gets difficult. The whole HTML string has to be added to the local resource, which isn't quite nice.
Solution 2 - Switch to TemplateFields
To get a solution that is better localizable, I delete the CommandField
column and add a template column that contains an ImageButton
. To get the same behaviour, the CommandName
has to be set to "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>
Custom Commands Sample
In order to get your custom commands to work, you can either use a ButtonField
with ButtonType
equal to Link
and use the same trick to display the image as in solution 1 or use a template field as in solution 2. I prefer solution 2, but be sure that you include the CommandArgument
in the definition, otherwise you won't have access to the row index.
The following sample shows this together with the approaches that do not work (see Tooltip for explanation as to what happens):
<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>
Conclusion
There exists a problem in Internet Explorer that leads to multiple PostBack
s when using a CommandButton
with type Image
. As long as this bug isn't fixed (or everybody uses FireFox;-)), we have to use some workarounds. In this article, I showed you three workarounds along with the scenario in which you can use them. In short: if you use template fields, you're always on the safe side.
If you have further information or other/better workarounds or even real solutions, then PLEASE post them below!!
History
- 2007-08-09 Initial version
- 2008-10-10 Changed template fields solution as proposed by Petr Behensky in his message post