I gave up on all the solutions I came up with once I realized that onload() event also gets fired twice.
And the worst part is when onload gets fired twice, the Page.IsPostBack sometimes returns false when it should return true, which automatically mess up all your initialization code.
Anyway, I finally understood the problem properly, it turns out there is a bug in the gridview that only happens if you use a command field of type image in one of your gridview columns.
You can avoid this error if you use a button type command field (instead of image).
Or in case you have to have an image to represent the delete button, you should completely ignore using the command field and use a template field instead.
Here is how a delete button tag should look like in your .aspx file when using a template field:
<asp:TemplateField>
<ItemStyle HorizontalAlign="Right" Width="10%"/>
<ItemTemplate>
<asp:ImageButton runat="server" id="btnDelete" CommandName="cDelete" ImageUrl="../resources/images/delete1.gif"
CommandArgument='<%# Eval("item_id") %>' OnCommand="OnDelete" />
</ItemTemplate>
</asp:TemplateField>
Note: the example above shows how you can pass a value of another column on the same row that you wish to delete (ex: item_id is a field of another column in the same row) to your event handler that can help you delete a record from the database.
You can also return the row number of the gridview in which you wish to delete by using DataBinder.Eval(Container,"RowIndex") instead of Eval(“your_column_name”)
And here is the code behind for handling the event “OnDelete”:
protected void OnDelete(object sender, CommandEventArgs e)
{
if (e.CommandName.Equals("cDelete"))
{
try
{
string item_id = e.CommandArgument.ToString();
// your code to delete the item record from
// your database using the index item_id
}
catch (Exception) { }
}
}