I’m working on slightly changing the functionality of a page in an ASP.Net website. In the original page there was a checkbox list written into the page with no items hard coded.
Instead on the initial render the cbl gets databound to the results of a query thus:
sSQL = "select query here";
using (SqlConnection dbcon = new DataAccess().OpenDb())
{
using (SqlDataReader dr = new SqlCommand(sSQL, dbcon).ExecuteReader())
{
cbl.DataTextField = "description";
cbl.DataValueField = "productid";
cbl.DataSource = dr;
cbl.DataBind();
}
dbcon.Close();
}
On a postback the following code:
foreach (ListItem li in cbl.Items) { if (li.Selected) rtnQS += li.Value + ","; }
Happily goes through the dynamic databound list items in the checkbox list and retrieves the checked values. I tried to do the same thing, putting an empty table on the page and then creating the rows dynamically:
sSQL = "similar select query here";
using (SqlConnection dbcon = new DataAccess().OpenDb())
{
using (SqlDataReader dr = new SqlCommand(sSQL, dbcon).ExecuteReader())
{
while (dr.Read())
{
TableRow tr = new TableRow();
TableCell tc = new TableCell();
CheckBox chk = new CheckBox();
chk.Text = dr["description"].ToString();
chk.InputAttributes.Add("id", dr["id"].ToString());
chk.Checked = true;
tc.Controls.Add(chk);
TableCell tc2 = new TableCell();
if (Convert.ToBoolean(dr["controlcondition"]))
{
CheckBoxList cbl_sub = new CheckBoxList();
cbl_sub.Attributes.Add("for", dr["id"].ToString());
sSQL = "subquery";
using (SqlConnection newcon = new DataAccess().OpenDb())
{
using (SqlDataReader br = new SqlCommand(sSQL, newcon).ExecuteReader())
{
cbl_block.DataTextField = "subname";
cbl_block.DataValueField = "subid";
cbl_block.DataSource = br;
cbl_block.DataBind();
}
}
tc2.Controls.Add(cbl_sub);
}
else
{
TextBox txtSub = new TextBox();
txtSub.Attributes.Add("for", dr["id"].ToString());
tc2.Controls.Add(txtSub);
}
tr.Cells.Add(tc);
tr.Cells.Add(tc2);
tblDispatchOpt.Rows.Add(tr);
}
}
dbcon.Close();
}
The only problem is that when the iterator comes to the table it only reads the hard coded header row. (The table renders beautifully with all the correct attributes on the original page though.)
Here’s the bit of code that tries to read the table rows:
foreach (TableRow row in tblDispatchOpt.Rows)
{
TableCell cell = row.Cells[0];
++counter;
foreach (Control c in cell.Controls)
{
if (c is CheckBox)
{
CheckBox cb = (CheckBox)c;
if (cb.Checked && cb.Attributes["ttid"] != null) dtTTInfo.Rows.Add(cb.Attributes["ttid"].ToString(), "", "");
}
}
}
Except that a debugging label check happily tells me there’s only one row and it’s the hard coded header row. So essentially doesn’t read the other rows as it seems the page doesn’t believe they exist when it comes to read them.
So why doesn’t it work with the table? Or, if it doesn’t work with the table for the usual reason that things don’t work with dynamic controls on postbacks e.g. rendering, lifecycle etc., why does it work with the checkboxlist?
You have to recreate dynamic controls on every postback if you want to get values from them.
You should do that in CreateChildControls() method.