Bookmark and Share BitCoin Donate: 13t8gAWVpHP2ddxMp88d1NFpZjnFJC6UwK

Gridview and dynamic controls

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);
	}