views:

403

answers:

2

Hey! 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?

+1  A: 

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
     }
   }
}
madatanic
Thanks I'll try this immediately. But isn't this what wouldn't work according the other post by Mike Mooney?
Phil
Buttons showed up but the event doesn't seem to get fired.. is this because of the reason mentioned below?
Phil
Instead of btn.Attributes.Add("OnClick", "btn_Clicked"); TRYbtn.Click += new EventHandler(btn_Clicked);
madatanic
+1  A: 

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.

Mike Mooney
So basically in Page_Init i create a DataTable Templeate that I fill with buttons? I'm not sure I'm following. Thanks for answering!
Phil