Well, I was refactoring some code today and wanted to convert an htmlbutton dynamically added to a gridview with autogenerated columns to an asp.net button so it could easily trigger serverside events.
During this process I stumbled on some weird gridview behaviour.
When accessing the Rows property of the gridview when the rows aren’t yet reconstructed, the Rows collection is immediately initialized with an empty one and the original rows aren’t recreated further in the gridview lifecycle. When the gridview is rendered again at the end of the requestcycle, the rows have disappeared.
Normally one would recreate the buttons in the OnInit but the gridview hasn’t reconstructed its rows collections yet and merely touching it clears it for good.
The solution is to recreate the buttons in OnPreload.
The gridviews Rows collection is already fully recreated and it’s still early enough to let asp.net trigger the buttons Click event.
Small sample:
If I would use the following code to create the buttons on the gridview:
private void EnsureButtons()
{
foreach (GridViewRow row in GridView1.Rows)
{
if (row.RowType == DataControlRowType.DataRow)
{
if (GetButton(row) == null)
{
row.Cells[0].Controls.Add(CreateButton(row));
}
}
}
}private Button GetButton(GridViewRow row)
{
return row.Cells[0].FindControl("DynamicallyCreatedButton_" + row.RowIndex) as Button;
}
private Button CreateButton(GridViewRow row)
{
Button button = new Button();
button.Text = "Dynamic Button";
button.ID = "DynamicallyCreatedButton_" + row.RowIndex;
button.Click += new EventHandler(button_Click);
return button;
}
void button_Click(object sender, EventArgs e)
{
Label1.Text = "Text set from dynamic button Click event";
}
I can create the buttons during the initial page request or after a new databind in the gridview prerender event:
protected void GridView1_PreRender(object sender, EventArgs e)
{
EnsureButtons();
}
And recreate them during postback in the OnPreLoad
protected override void OnPreLoad(EventArgs e)
{
EnsureButtons();
base.OnPreLoad(e);
}
February 11, 2009 at 10:13 am
DUDE !! You rock !!
I’ve spent the last three days on a grid which adds dynamic rows and buttons based on the info in the grid.
My events was firing initially, but then as the grid got more complex they just stopped. I tried to go back step by step, but it’s so damn complex it was just way too time consuming.
Came across your post and gave it a go. Firstly, failure because my grid was in a UserControl which does not provide OnPreLoad. So i overrode preload in the parent page and then just called an ‘EnsureButtons’-like method from there. This brought up a whole bunch of other intricicies, but at least my events are firing again !!
Anyway, kudos to you!
February 17, 2009 at 8:09 pm
Wow… I have spent the last 6 hours trying to get this to work, and your little preload in the page works like a dream
)
Many Thanks
March 17, 2009 at 2:16 pm
Genial! muchas gracias… llevaba un día entero sin saber porque no funcionaban los botones del GridView, gracias a tu ayuda lo pude conseguir.
Gracias, saludos.
April 22, 2009 at 9:59 pm
Hi, I’m trying to insert some dynamic linkbutton inside the rows of a gridview.
1. I First generate the columns inside a datatable.
//Create an instance of DataTable
DataTable dt = new DataTable();
DataColumn dcol = new DataColumn(“Measure”, typeof(System.String));
dt.Columns.Add(dcol);
for (int i = 1; i < 5; i++)
{
//Create an ID column for adding to the Datatable
dcol = new DataColumn(i.ToString(), typeof(LinkButton));
dt.Columns.Add(dcol);
}
2.then, I created a row and add it to the datatable
for (int i = 1; i < 5; i++)
{
try
{
LinkButton btnTest = new LinkButton();
btnTest.ID = “btn” + i; // you can change the id , the way you want it
btnTest.Text = “0″;
btnTest.Visible = true;
drow[i.ToString()] = btnTest;
}
catch (Exception ex)
{
Response.Write(ex.Message);
}
}
dt.Rows.Add(drow);
3. At last I initialize the data source and bind the datatable with the gridview.
//Initialize the DataSource
GridViewScorecard.DataSource = null;
GridViewScorecard.DataBind();
GridViewScorecard.DataSource = dt;
//Bind the datatable with the GridView.
GridViewScorecard.DataBind();
THE PROBLEM WITH THIS CODE IS THAT THE GRIDVIEW DOESN’T SHOW ANYTHING BUT THE DATATABLE HAS THE DATA CORRECT, BUT IN THE DATA BINDING EVERYTHING IS LIKE “LOST”
thanks for your responses and help.
May 14, 2009 at 9:47 pm
Thank you. I spent 3 hours looking for this.
September 10, 2009 at 2:42 pm
Hi! I was surfing and found your blog post… nice! I love your blog.
Cheers! Sandra. R.
September 23, 2009 at 8:59 pm
Great! This post really help me out!
Thanks!