ASP.Net Dynamic Controls (Part 1)
If you have ever tried to work with dynamic controls in ASP.Net you’ve probably run afoul of the tons of limitations and pulled a good number of hairs out. It shouldn’t be this difficult should it? I don’t think so! The main issue with dynamic controls is that they don’t really fit into the ASP.Net Page framework since they don’t exist when ASP.Net is doing all its behind the scenes work.
These are the typical problems with dynamic controls:
- Controls must be created in Page_Init or Page_Load for Event Handlers to work
- All dynamic controls must be regenerated every time the page loads
- Collecting the data after a postback is difficult since controls no longer exist
- Control constructors don’t set many parameters which makes configuration tedious
- The methods available to add a control to the page vary depending on where it is created
As you can see the rigidity of the ASP.Net framework causes the programmer a lot of grief compared to languages like PHP that use raw HTML elements for everything and have no server side controls. You can’t really complain though since at the same time as it is limiting it is very powerful and saves a lot of programming hours. In this series I will address some of the issues listed above and make this a very useful resource for programmers like myself who like to live on the edge of the framework. Alright so first things first lets take a look at a basic example of how to create a dynamic control.
Sub Page_Load
Dim cmd As New Button()
cmd.Text = "Button 1"
AddHandler cmd.Click, AddressOf Button_Click
phPage.Controls.Add(cmd)
End Sub
…
<asp:PlaceHolder ID="phPage" runat="server />
This very simple example illustrates how to create a dynamic button on a web form. It would be very simple using a loop to create an arbitrary number of buttons each with different text and different event handlers, but wait. Why would you go through all that pain to create so many event handlers when it could be done using one? If you are not familiar with the Command Event you are really missing out. It operates in the same way as a standard Click except it allows for two parameters to the Event Sub. Lets take another look at our example using this method.
Sub Page_Load
Dim cmd As New Button()
cmd.Text = "Button 1"
cmd.CommandName = "ButtonGroupName"
cmd.CommandArgument = "WhichButtonInGroup"
AddHandler cmd.Command, AddressOf Button_Click
phPage.Controls.Add(cmd)
End Sub
Sub Button_Click (ByVal s As Object, ByVal e As CommandEventArgs)
If e.CommandName = "ButtonGroupName" Then
If e.CommandArgument = "WhichButtonInGroup" Then
…
End If
End If
End Sub
…
<asp:PlaceHolder ID="phPage" runat="server />
Any type of button can be used for this since ASP.Net considers them all equally. However, when it comes to other non-button controls it becomes a bit more challenging. Just say you wanted to create a list from a database that gives the viewer a set of tools for each item in the list, for example we need a checkbox to record a boolean value. The first step is to generate the list with the check boxes. Some people like to do this in a Sub and others directly on the page. In either case you will still need a PlaceHolder control. Lets looks at code to generate the checkboxes.
Sub Generate_List (ByRef rdr As SqlDataReader)
Dim chk As CheckBox
While rdr.Read()
phPage.Controls.Add(New LiteralControl("HTML and Data"))
chk = New CheckBox()
chk.ID = rdr("item_id")
phPage.Controls.Add(chk)
phPage.Controls.Add(New LiteralControl("HTML and Data"))
End While
End Sub
…
<asp:PlaceHolder ID="phPage" runat="server />
There is not much difference between this and the dynamic button code above. We don’t have an event handler for the checkbox because we don’t want anything to happen after clicking each checkbox instead there will be one save button at the bottom of the page. The major thing to note from this example is the use of the ID field. Without this field every checkbox would be the same and we wouldn’t know which goes with each entry in the list when processing the form on postback. So lets see how we would use the data, remember from earlier that dynamic controls disappear on postback so we can’t use ID.Checked to find out the value.
Sub Save_Click (ByVal s As Object, ByVal e As EventArgs)
…
rdr = cmd.ExecuteDataReader()
While rdr.Read()
If String.IsNullOrEmpty(Request.Form(rdr("item_id"))) Then
… 'Checkbox wasn't checked
Else
… 'Checkbox was checked
End If
End While
rdr.Close()
…
End Sub
This fragment probably looks a little strange but let me explain what is going on. We can’t access the posted value of each checkbox through its control name natively since after postback it no longer actually exists in the page. What we do have left is the posted values in the Request.Form collection just as in a standard HTML form. So we just need to go through the list of checkboxes that we added and check what the value is set to. The same process will work on any other form data containers in the same way. This next example will be the last for this part and shows the issues with advanced techniques.
Sub Page_Load
Dim btn As Button
…
rdr = cmd.ExecuteDataReader()
While rdr.Read()
btn = New Button()
btn.Text = "X"
btn.CommandName = "Delete"
btn.CommandArgument = rdr("item_id")
AddHandler btn.Command, AddressOf Button_Click
phPage.Controls.Add(btn)
End While
rdr.Close()
…
End Sub
Sub Button_Click (ByVal s As Object, ByVal e As CommandEventArgs)
… ' Delete list item whose delete button was click
End Sub
…
<asp:PlaceHolder ID="phPage" runat="server />
You are probably thinking “Everything looks alright to me, what’s wrong with it?”. Well the answer lies in the order of page events. Page_Load fires before any user event handlers so you have already regenerated the list before the element is deleted which means its still on the page. “Well that is a simple fix right?, just move the list generation code into a function and call it at the end of the Button_Click event”. Sure sounds good to me, unfortunately if you create the buttons after Page_Load the event handlers won’t actually work and your page will be filled with dead buttons. “So what is the answer” you ask. For now all I will say is the solution requires a bit of JavaScript. Of course there are other possibilities as is common in programming and they are all very hacky so pick your poison if you like, if not stay tuned for the next part. Same RSS channel same RSS time, which doesn’t really make sense but gives me a chance to use that very excellent anachronism.
ASP.Net Dynamic Controls (Part 2) »
ASP.Net Dynamic Controls (Part 3) »
ASP.Net Dynamic Controls (Part 4) »
Categories
Recent
- Browser Logo Shootout
- Blackberry Surreal Theme
- Blackberry JDE API - User Interface Field Reference
- Getting started with the Blackberry Java Development Environment (JDE)
- ASP.Net DropDownList annoyance
- Getting a Blackberry Curve
- Mambo to the beat of the internet
- ASP.Net has 9 to 5 appeal
- ASP.Net CheckBoxes should be able to have values
- Time to take a look at Python I guess
- Country list formatted for MySQL import
- Kinetic Typography: typographic treatment of an audio sample
- MSN Video Sucks
- Five things about me
- Blackberry MP3 Player Instructions



I figured checkboxes would be the same as textboxes.
Here is what I am using:
Checkbox chk = new CheckBox();
//rdrAllA is an oledbdatareader, and I want to place the Id value from the table into the checkbox ID, strAName is a common name for every checkbox that is rendered (ex. strAName = “fun”)
chk.ID = strAName + rdrAllA["Id"]; chk.Text = strAName + rdrAllA["Id"]; phFun.Controls.Add(chk); phFun.Controls.Add(new LiteralControl(”"));
When I open the page, I do not see any checkboxes at all. When I step through the code it acts as if these checkboxes are being rendered. Any Ideas?
I would say that it is either the placement of the PlaceHolder control in your HTML or something in the way you add the checkboxes to it.
One thing to note is that you must add the controls to the PlaceHolder before the definition of the tag (ie the <asp:PlaceHolder /> code). If you add them after they will not render.
Another thing to note (although not your issue) is that if you don’t generate a new CheckBox object for each entry you will only end up with one rendered at the end since really you have only put one object in the PlaceHolder.
If that doesn’t solve your problem send me your code, I can take a look at it for you. ahewgill@gmail.com
Good and Helpfull
I find the use of dynamic, bound checkboxlist control to be straightforward, very useful, but with the usual layout problems of dynamically generated controls.
This example creates a range of checkboxlists by category, binds each to a datasource, and sets the checked property of each.
First get the Checkboxlist topics
This works (The example code above is edited as an explanation). However, I’ve got very little control over layout. I’d like to start each CheckBoxList on its own line, preceeded by a label. However each control appears to be enclosed in an inherent tag.
Hi,
I added the dynamic controls and when i am clicking a dynamic button, the postback is fired and the dynamic controls are cleared. pls give an idea how to retreive the dynamic controls and data entered in them.
Thanks in advance
The second last code example shows how to collect the values back from the checkboxes after postback. You need to have a list of the IDs you used (using the same method you generated them with initially) and then just lookup the value in Request.Form. Also dynamic controls do not reappear on their own, you must redraw them on postback or your page will only have the static controls on it.
I came accross this situation with a dynamically generated web form for a project that I created. The solution to the problem of being able to iterate through the controls when posting back was to create the form in the LoadViewstate Override
Protected Overrides Sub LoadViewState(ByVal savedState As Object)
LoadEscalationTable()
End Sub
where sub loadEscalationTable creates dynamic asp:rows and asp:columns containing dynamic dropdownlist controls with names and Id’s of email recipients. This worked out to be a foolproof solution for persisting dynamic data on a page for postback. Hope this helps.
-Gene
Great solution!
One comment though. I create the checkboxes in the Page_Load method of the form. On postbacks, the state of the checkboxes persists. I was expecting the checked property for all the checkboxes to be cleared since they’re being recreated on every postback but this doesn’t happen. The ones that were checked before the postback remain checked.
I am trying to add LinkButtons in a web page which is inside a Master Page but I cannot catch the click event.
Then I tried the same on a separate web page and it works.
Why it is not working in the first case when my web page is inside a Master Page.
Please help me.
I tried the checkbox on my code page but it wasnt working. I was gettting the id as u did but couldnt get the checked properties. so i used urs and the same thing is still happening.
hi
i utilize these controls in prj these dyamically
controls are useful while pls send the code
of combobox,gridview control code dynamically
chandu(:-
i want define dynamic chechkbox and when i click on it(CheckedChanged) the visible of my button become true.
please help me
thaks
Hi
I tried to fire the Button click event on Dynamic button control. But it’s won’t fire.
Please anyone help me
thanks
how can i fire event on dynamically generated button.
problem is that:
i generate dynamically 3 dropdown list and one button on click of static button.
when i click on dynamic generate button then all dynamic generate controlls hide then how can i catch selected value of dropdown list..
for further process………
Hi Gene.
Thanks alot for your help.
Actually i was created dynamic checkbox control in gridview. The procedure i am decribing….
Firstly i bounded the gridview with datasource. Then with Row DataBound eg (protected void gvData_DataBound(object sender, GridViewRowEventArgs e)), i created the dynamic checkbox control.
Then i used viewstate eg -
protected override void LoadViewState(object savedState)
{
BindGrid();
base.LoadViewState(savedState);
}
Its successfully work.
Hope it help.
Hi Arvind,
For dynamic generated button, you can add event on row databound event.
Eg.
protected void gvData_DataBound(object sender, GridViewRowEventArgs e)
{
foreach (GridViewRow Row in GrdViewSearch.Rows)
{
for (int i = 0; i < Row.Cells.Count; i++)
{
if (Row.Cells[i].Text == “1″)
{
CheckBox chkCheckBox = new CheckBox();
TableCell tcCheckCell = new TableCell();
tcCheckCell.ID = “tcCell” + i;
chkCheckBox.ID = “_#_CHK_#_” + i;
chkCheckBox.Checked = true;
chkCheckBox.Attributes.Add(”onClick”, “SelectOneDynamic(this.id, this.checked);”);
tcCheckCell.Controls.Add(chkCheckBox);
Row.Cells.RemoveAt(i);
Row.Cells.AddAt(i, tcCheckCell);
}
Actually in my dataset, the checkbox value has 1 or 0.
So i am replacing that particular “CELL” with checkbox cheked.
Hope it will help
Hi,
I have a question concerning dynamically created linkbuttons.
I have a webpage where I create in the page_load event about 10.000 linkbuttons dynamically. Each of them gets a unique ID of course and all of the share the same click event handler (but with different command arguments).
When one of these linkbuttons is clicked, a pageback occurs. I understand, that I have to recreate the dynamically created linkbuttons (and I’ve seen that this works) - but creation of 10.000 buttons takes quite a while. I would prefer to only recreate the one which was actually pressed and then call the click method defined in the event handler (with the arguments assigned to the button).
Is this possible? It might be sufficient to get the ID of the clicked button. How do I retrieve this ID?
This is what I was looking for for hours all over the internet. By far the best solution out there.
Thank you!
[...] am not going to tell you all sorts of ways to accomplish this since some guys out there have already done this. And I learned from them. Here is how I like to do [...]