Search code examples
c#htmlfindcontrol

FindControl and Get Selected Value of Dropdown


This scenario is occurring when using C# code behind to find HTML Controls added dynamically from SQL Data Results.

Using the following there is an iteration though the Table rows and row each table row, we write the Controls value, in this case a HtmlSelect. The Html Select Element is in Cell 3

for (int i = 1; i <= Table1.Rows.Count - 1; i++)
{
     HtmlSelect select = Form.FindControl("MainContent_selectBoxstatus" + i) as HtmlSelect;
     System.Diagnostics.Debug.Write(select.Value);
}

Resulting in:

A first chance exception of type 'System.NullReferenceException' occurred in project.dll

If i use the following:

for (int i = 1; i <= Table1.Rows.Count - 1; i++)
    System.Diagnostics.Debug.Write(Table1.Rows[i].Cells[0].Text);

I get the desired result, of the text from Cell 1.

How the Select Dropdown is created:

for (int i = 0; i < dr.FieldCount; i++)
   HtmlSelect sStatus = new HtmlSelect();
   sStatus.Items.Add(new ListItem("Working", "0"));
   sStatus.Items.Add(new ListItem("Fault", "1"));
   sStatus.SelectedIndex = 0;
   sStatus.Attributes.Add("class", "dropdownlist");
   sStatus.ID = "selectBoxstatus" + rowindex;
   cell.Controls.Add(sStatus);

Solution

  • That's what usually happens when you are trying to "hack" ASP.NET internals. I mean "hack" because using magic strings to resolve the auto-generated ids assigned to child controls is extremely unsafe. There are much better and safer ways to do this.

    1- If you want to render a tabular layout, I'd strongly recommend using a databound control such as a GridView, ListView, etc where you can intersect its RowDatabound event and retrieve the child controls in a safe manner

    2- If you can't afford to do a re-write then replace your code as follows...

    for (int i = 0; i < Table1.Rows.Count; i++)
    {
         HtmlSelect select = Table1.Rows[i].Cells[0].FindControl(string.Format("selectBoxstatus{0}", i)) as HtmlSelect;
    
         if(select != null)
             System.Diagnostics.Debug.Write(select.Value);
    }
    

    Option 2 Code Analysis

    for (int i = 0; i < Table1.Rows.Count; i++)
    

    Nitpicking, but initializing i to 0 this makes it easier to read...believe it

    HtmlSelect select = Table1.Rows[i].Cells[0].FindControl(string.Format("selectBoxstatus{0}", i)) as HtmlSelect;
    

    I'm not too sure what Form meant in your original post but it makes more sense to use the object you're iterating....Table1 rows collection. I also refer to Cell[0] which is the first cell in the iteration's current row(feel free to adjust it)...this is still not safe but it's the only way to achieve it in the current scenario, if you need more code safety, then resort to option one. Also notice that FindControl doesn't mess around with auto-generated id, it simply uses the actual Id specified for the child control

    if(select != null)
    

    After you attempt to retrieve the select control make sure to check whether the control was successfully retrieved or not.

    Hope it makes sense