In a GridView, how to add multiple commands to one item template?

5.1k views Asked by At

I stripped this example to make it simple. I have a gridview with a template field. The template field contains two buttons and a label (They must be in the same template field). I want the first button to set the label text to "Win", and the other button to set the label text to "fail". The onrowcommand doesnt seem to be triggered by buttons in a template field. How can I accomplish this?

My gridview code is below:

        <asp:GridView ID="GridView1" runat="server" EnableModelValidation="True" AutoGenerateColumns="False"
        OnRowCommand="Gridview1_RowCommand">
        <Columns>
            <asp:TemplateField ShowHeader="False">
                <ItemTemplate>
                    <asp:Button ID="btnWin" runat="server" CommandName="Win" Text="Win" />
                    <asp:Button ID="btnFail" runat="server" CommandName="Fail" Text="Fail" />
                    <asp:Label ID="lblStatus" runat="server" Text='<%# Bind("text") %>'></asp:Label>
                </ItemTemplate>
            </asp:TemplateField>
        </Columns>
    </asp:GridView>

and my code behind:

    protected void Page_Load(object sender, EventArgs e)
    {
        DataTable myTable = new DataTable();
        myTable.Columns.Add("text", typeof(string));
        myTable.Rows.Add("First Entry");
        myTable.Rows.Add("Second Entry");

        GridView1.DataSource = myTable;
        GridView1.DataBind();
    }

   public void Gridview1_RowCommand(Object sender, GridViewCommandEventArgs e)
    {
       //set lblStatus.text to "Win", or "Fail"
    }

Thanks in advance!

2

There are 2 answers

0
Grant Thomas On BEST ANSWER

Here you go...

public void Gridview1_RowCommand(Object sender, GridViewCommandEventArgs e)
{
   lblStatus.Text = e.CommandName;
}

I see that there is more to this question than is answered here, bear with me. One way would be to delegate the OnCommand event of each button to its designated event handler, as follows:

<div>
    <asp:GridView ID="MyGridView" runat="server" EnableModelValidation="true" AutoGenerateColumns="False">
        <Columns>
            <asp:TemplateField ShowHeader="False">
                <ItemTemplate>
                    <asp:Button ID="MyWinButton" runat="server" OnCommand="MyWinButton_OnCommand" CommandName="Win" Text="Win" />
                    <asp:Label ID="MyStatusLabel" runat="server" Text='<%# Bind("text") %>'/>
                </ItemTemplate>
            </asp:TemplateField>
        </Columns>
    </asp:GridView>
</div>

public void MyWinButton_OnCommand(Object sender, CommandEventArgs e)
{
    var label = ((Button)sender).Parent.FindControl("MyStatusLabel") as Label;
    label.Text = e.CommandName;        
}

Also, as Alison suggests, you won't see the desired output of this unless you use !IsPostBack in Page_Load. Furthermore, on doing so this does in fact enable you to use the one row command event handler as initially suggested, albeit with a slight change in the label retrieval:

public void MyGridView_OnRowCommand(Object sender, GridViewCommandEventArgs e)
{
    var label = ((Button)e.CommandSource).Parent.FindControl("MyStatusLabel") as Label;
    label.Text = e.CommandName;
}
1
NakedBrunch On

Are you using a MasterPage with ViewState turned off? Buttons in a template field with ViewState set to false will not fire.

Also, you should change your Page_Load to NOT rebind on postback"

protected void Page_Load(object sender, EventArgs e)
    {
      if (!page.IsPostBack) {
        DataTable myTable = new DataTable();
        myTable.Columns.Add("text", typeof(string));
        myTable.Rows.Add("First Entry");
        myTable.Rows.Add("Second Entry");

        GridView1.DataSource = myTable;
        GridView1.DataBind();
      }
    }

The rebinding may be interfering.