How do I programmatically add a button to a gridview and assign it to a specific code-behind function?

StackOverflow https://stackoverflow.com/questions/2418379

Question

In runtime I'm creating a DataTable and using nested for-loops to populate the table. This table I later assign as DataSource to a gridview and on RowDataBound I assign the value of each cell. I want to know how I can give each cell a button and assign that button to a codebehind function. I'll have 12 buttons and each one will contain a different value. I would prefer if they all call the same function with some kind of event that stores the cell-specific value.

This is the code where the Table gets created:

protected void GridViewDice_RowDataBound(object sender, GridViewRowEventArgs e)
{


    DataTable diceTable = _gm.GetDice(_gameId);
    for (int i = 0; i < GameRules.ColumnsOfDice; i++)
    {
        if(e.Row.RowIndex > -1)
        {
            /*This is where I'd like to add the button*/
            //e.Row.Cells[i].Controls.Add(new Button);
            //e.Row.Cells[i].Controls[0].Text = specific value from below

            //This is where the specific value gets input
            e.Row.Cells[i].Text = diceTable.Rows[e.Row.RowIndex][i].ToString();
        }

    }
}

I would like to handle the buttonclick with something like this:

protected void DiceButton_Click(int column, int row, int value)
{
    //Do whatever
}

Any suggestions?

Was it helpful?

Solution

On your gridview in markup, assign CommandArgument attribute to whichever you want (here I choose the index of the current gridviewrow) inside the your buttons.

 <asp:Button ID="lbnView" runat="server" Text="Button" OnClick="btn_Clicked" 
CommandArgument="<%# ((GridViewRow)Container).RowIndex %>"></asp:Button>

Or in your code behind, you can create a button like below

protected void GridViewDice_RowDataBound(object sender, GridViewRowEventArgs e) 
{ 


    DataTable diceTable = _gm.GetDice(_gameId); 
    for (int i = 0; i < GameRules.ColumnsOfDice; i++) 
    { 
        if(e.Row.RowIndex > -1) 
        { 
            Button btn = new Button();
            btn.CommandArgument = diceTable.Rows[e.Row.RowIndex][i].ToString(); 
            btn.Attributes.Add("OnClick", "btn_Clicked");

            e.Row.Cells[i].Controls.Add(btn);
        }
    }
}

then make an event handler like below

protected void btn_Clicked(object sender, EventAgrs e)
{
   //get your command argument from the button here
   if (sender is Button)
   {
     try
     {
        String yourAssignedValue = ((Button)sender).CommandArgument;
     }
     catch
     {
       //Check for exception
     }
   }
}

OTHER TIPS

Unfortunately at that stage you can't create a new button and assign events to it. By this point in the page lifecycle, when it's firing events, it has already built up it's list of "known" controls that it will keep track of when the page reloads, and so it won't know to fire your button click event code the next time it posts back.

In order to get ASP.NET to properly fire your event methods, you need to add the Button control to the page's control hierarchy before the page's Load event. I usually do it in the Init event or CreateChildControls method.

To solve your issue, I would recommend adding the button to all the cells in the template markup and have it reference the event handler there. Then, have your RowDataBound method handle flip the button's visibility on or off.

The easiest way to do this is just add a column to your GridView (You can use a button rather than a hyperlink if you like):

<Columns>
 <asp:HyperLinkField DataNavigateUrlFields="ID" DataNavigateUrlFormatString="~/pUser.aspx?field={0}" HeaderText="Select" Text="Select" />

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top