The part 3 of this series was getting a bit long for my taste so I decided to break it in 2. Here we’ll continue dealing with the controls added dynamically to our page only now we’re going to access them by ID.
Related posts:
Naming the controls
By now you have noticed that we haven’t explicitly set the ID of any of our controls. Of course the controls have ID’s but they are defined automatically by the Asp.Net framework when the controls are instantiated. The reason this works is because the framework will create the names consistently the same, again and again as long as you create the controls always in the same order (we are doing that).
It is this automatically naming feature that allows our components to keep their state between requests. When the page is submitted all of the controls states are sent back from the browser to the server, but the server doesn’t know how to create the controls that’s why we had to do it every time the page is submitted. After the control has been created the Asp.Net framework is able to get it’s state from the page based on it’s name.
Ok, enough theory. Let’s give our controls and ID manually. Since the controls are added dynamically the ID’s have to be something that can be predicted. Let’s say: TextBox + a number. For this will change the createDynamicControls method to add a parameter which will be the number of the control added.
//this method takes care of creating the controls
private void createDynamicControls(int count)
{
TextBox tb = new TextBox();
tb.TextChanged += TextBox_TextChanged;
//now we set the control ID manually
tb.ID = "TextBox" + count;
PlaceHolder1.Controls.Add(tb);
controlsList.Add(tb);
}
When the add control button is clicked we need to pass the number to the method. We can use the control count that we’re storing in the ViewState.
protected void Button1_Click(object sender, EventArgs e)
{
createDynamicControls((int)ViewState["count"]);
//increment the number of controls
ViewState["count"] = (int)ViewState["count"] + 1;
}
Another place we need to change is the Page_Load event when the controls are re-created. Here for loop when we pass in the new parameter:
for (int i = 0; i < controlCount; i++)
{
//notice that now we pass the i as parameter
createDynamicControls(i);
}
To test our new functionality we will add TextBox, a Button and a Label. We are going to inform the ID of the TextBox we want to get the value for. When the button is clicked the event will get the control and display it’s value in the label.
<asp:TextBox ID="TextBoxControlId" runat="server"></asp:TextBox>
<asp:button ID="ButtonGetValue" runat="server" text="Get value"
onclick="ButtonGetValue_Click" />
Valor: <asp:Label ID="LabelValue" runat="server" Text=""></asp:Label>
And here is the event where we get the TextBox we want:
protected void ButtonGetValue_Click(object sender, EventArgs e)
{
//find the control we want using the name informed by the user in the
//TextBoxControlId control
TextBox tb = (TextBox)PlaceHolder1.FindControl(TextBoxControlId.Text);
LabelValue.Text = tb.Text;
}
Now if you add 3 TextBoxes (which will have id’s TextBox0, TextBox1 and TextBox2) and you input TextBox0 in the interface and hit the button the LabelValue control will show the value in the first TextBox.
This one was a bit longer than I would like to so I’ll try to make the next article shorter.
Here is the final version of our page after all of our modifications:
<%@ Page Language="C#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">
System.Collections.Generic.List<TextBox> controlsList = new System.Collections.Generic.List<TextBox>();
void Page_Load(object sender, EventArgs e)
{
//when the user first enters the page set the count as zero
if (!IsPostBack)
{
ViewState["count"] = 0;
}
//on every subsequent postback, check the control count
//and recreated all the controls
else
{
int controlCount = (int)ViewState["count"];
for (int i = 0; i < controlCount; i++)
{
//notice that now we pass the i as parameter
createDynamicControls(i);
}
}
}
protected void Button1_Click(object sender, EventArgs e)
{
createDynamicControls((int)ViewState["count"]);
//increment the number of controls
ViewState["count"] = (int)ViewState["count"] + 1;
}
//this method takes care of creating the controls
private void createDynamicControls(int count)
{
TextBox tb = new TextBox();
tb.TextChanged += TextBox_TextChanged;
//now we set the control ID manually
tb.ID = "TextBox" + count;
PlaceHolder1.Controls.Add(tb);
controlsList.Add(tb);
}
private void TextBox_TextChanged(object sender, EventArgs e)
{
//the sender is the control that fired the event
//that is the control we want to change the color
TextBox tb = (TextBox)sender;
tb.BackColor = System.Drawing.Color.Yellow ;
}
protected void ButtonAdd_Click(object sender, EventArgs e)
{
int value = 0;
foreach (TextBox tb in controlsList)
{
value += int.Parse(tb.Text);
}
LabelTotal.Text = value.ToString();
}
protected void ButtonGetValue_Click(object sender, EventArgs e)
{
//find the control we want using the name informed by the user in the
//TextBoxControlId control
TextBox tb = (TextBox)PlaceHolder1.FindControl(TextBoxControlId.Text);
LabelValue.Text = tb.Text;
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:PlaceHolder ID="PlaceHolder1" runat="server"></asp:PlaceHolder>
<br />
<asp:Button ID="Button1" runat="server" Text="Add TextBox"
onclick="Button1_Click" />
<br />
<asp:Button ID="ButtonAdd" runat="server" Text="Add all values"
onclick="ButtonAdd_Click" />
<br />
Total:<asp:Label ID="LabelTotal" runat="server" Text=""></asp:Label>
<br />
<br />
<asp:TextBox ID="TextBoxControlId" runat="server"></asp:TextBox>
<asp:button ID="ButtonGetValue" runat="server" text="Get value"
onclick="ButtonGetValue_Click" />
Value: <asp:Label ID="LabelValue" runat="server" Text=""></asp:Label>
</div>
</form>
</body>
</html>
See you next time.