Question

I am working on a solution in C# and ASP.NET 4.0 I am trying to get the value of a radiobutton from my page that was dynamically created based on some database information.

Here is what gets generated in the page source:

<td>
  <input id="masterMain_3Answer_0" type="radio" name="ctl00$masterMain$3Answer"     
    value="Y" onclick="return answeredyes(3);" />
  <label for="masterMain_3Answer_0">Y</label>
</td>
<td>
  <input id="masterMain_3Answer_1" type="radio" name="ctl00$masterMain$3Answer" 
    value="N" onclick="return answeredno(3,&#39;desc&#39;);" />
  <label for="masterMain_3Answer_1">N</label>
</td>

Inside the OnClick function of my submit button I want to gather wether Y or N has been selected based on the user's input.

Here is what I have written so far:

      RadioButton _rbAnswer = new RadioButton();
      RadioButtonList _rbList = new RadioButtonList();


     ContentPlaceHolder cp = (ContentPlaceHolder)Master.FindControl("masterMain");
     _rbAnswer = (RadioButton)Master.FindControl("masterMain_3Answer_0");
     HtmlInputRadioButton rb = (HtmlInputRadioButton)Master.FindControl("masterMain_3Answer_0");


     _rbAnswer = (RadioButton)cp.FindControl("masterMain_3Answer_0");
     _rbList = (RadioButtonList)cp.FindControl("masterMain_3Answer_0");

I am able to get the ContentPlaceHolder without any issues but the rest of the objects are null after it attempts to get the . I have also attempted removing the "masterMain_" but still doesn't want to find the controls.

Here is the code in which the individual radiobuttonlists are added

                TableRow _tempRow = new TableRow();
                TableCell _cellOK = new TableCell();


                 RadioButtonList _rbList = new RadioButtonList();
                _rbList.ID = r[0].ToString()+"Answer";
                _rbList.RepeatDirection = RepeatDirection.Horizontal;

                //add options for yes or no
                 ListItem _liOk = new ListItem();
                _liOk.Value = "Y";
                 ListItem _linotOk = new ListItem();
                _linotOk.Value = "N";
                _rbList.Items.Add(_linotOk);

                //add cell to row
                _rbList.Items.Add(_liOk);
                _cellOK.Controls.Add(_rbList);
                _tempRow.Cells.Add(_cellOK);

                 //add the row to the table
                 stdtable.Rows.Add(_tempRow);
Was it helpful?

Solution

To be able to quickly find dynamically created controls, add a dictionary to your page class:

private Dictionary<string, Control> fDynamicControls = new Dictionary<string, Control>();

then when a new control is created in code and its ID is assigned:

fDynamicControls.Add(newControl.ID, newControl);

and when you need control's reference:

Control c = fDynamicControls["controlIdThatYouKnow"];

OTHER TIPS

When using FindControl don't use the id that's generated by the page. Use the ID that you specified inthe aspx.

If this is inside a Repeateror another DataBound control, you have to first find the current record. (GridViewRow or RepeaterItem) first, an use that item's .FindControl function.

See this (different - not duplicate) question to see a code example of how to do it: How to find control with in repeater on button click event and repeater is placed with in gridview in asp.net C#

When you create dynamic controller give specific ids for them. This facilitate to generate controls with our own id. therefore then we can access the controls with this id.

And also use OnInit life cycle event to generate dynamic controllers, this is the best place to generate them.

 RadioButton _rbAnswer = new RadioButton();
 _rbAnswer.ID="ranswerid";

Given your update, you'll find that your control heirarchy is fairly deep. You have a RadioButtonList inside a cell inside a row inside a table ...

FindControl is a method that needs to be called on a specific object and can only find objects that are actual children of that object. In this case, you either need to build a recursive method or go directly to the control in question. Since so many of these controls are generated dynamically, you'll have no real way of accessing them directly so building the recursive function may be simplest. However, on very large pages this method can be very resource consuming:

public static WebUserControl FindControlRecursive(this WebUserControl source, string name) 
{
    if (source.ID.Equals(name, StringComparison.Ordinal))
        return source;

    if (!source.Controls.Any()) return null;

    if (source.Controls.Any(x => x.ID.Equals(name, StringComparison.Ordinal))
        return source.FindControl(name);

    WebUserControl result = null;

    // If it falls through to this point then it 
    // didn't find it at the current level
    foreach(WebUserControl ctrl in source.Controls)
    {
        result = ctrl.FindControlRecursive(name);
        if (result != null) 
            return result;
    }

    // If it falls through to this point it didn't find it
    return null;
}

This is an extension method that would allow you to call this on your ContentPlaceHolder control:

var _cp = (ContentPlaceHolder)Master.FindControl("masterMain");
RadioButtonList _rbList = _cp.FindControlRecursive("3Answer");

if (_rbList != null)
   // ... Found it

Note: Treat the above as psuedo-code. It has not be implemented by me anywhere so may (likely) require tweaking to behave exactly right.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top