FindControl返回null

时间:2012-12-21 18:10:33

标签: c# asp.net master-pages contentplaceholder

我正在研究C#和ASP.NET 4.0中的解决方案我试图从我的页面获取基于某些数据库信息动态创建的单选按钮的值。

以下是在页面源中生成的内容:

<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>

在我的提交按钮的OnClick功能中,我想收集根据用户的输入选择Y或N.

这是我到目前为止所写的内容:

      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");

我能够在没有任何问题的情况下获取ContentPlaceHolder,但其余的对象在尝试获取之后为null。我也尝试删除“masterMain_”,但仍然不想找到控件。

以下是添加单个放射性黑名单的代码

                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);

4 个答案:

答案 0 :(得分:2)

为了能够快速找到动态创建的控件,请在页面类中添加一个字典:

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

然后在代码中创建新控件并分配其ID:

fDynamicControls.Add(newControl.ID, newControl);

当你需要控制的参考时:

Control c = fDynamicControls["controlIdThatYouKnow"];

答案 1 :(得分:0)

使用FindControl时,请勿使用页面生成的ID。使用您在aspx中指定的ID。

如果这是在Repeateror中的另一个DataBound控件,则必须先找到当前记录。 (GridViewRow或RepeaterItem)首先,使用该项的.FindControl函数。

请参阅此(不同 - 不重复)问题,以查看如何执行此操作的代码示例:How to find control with in repeater on button click event and repeater is placed with in gridview in asp.net C#

答案 2 :(得分:0)

创建动态控制器时,为它们提供特定的ID。这有助于使用我们自己的id生成控件。因此,我们可以使用此ID访问控件。

并且还使用OnInit生命周期事件来生成动态控制器,这是生成它们的最佳位置。

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

答案 3 :(得分:0)

鉴于您的更新,您会发现您的控件层次很深。你在一个表内的一行内的单元格内有一个RadioButtonList ...

FindControl是一种需要在特定对象上调用的方法,只能找到该对象的实际子对象。在这种情况下,您需要构建递归方法或直接转到相关控件。由于这些控件中有很多是动态生成的,因此您无法直接访问它们,因此构建递归函数可能是最简单的。但是,在非常大的页面上,此方法可能非常耗费资源:

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;
}

这是一种扩展方法,允许您在ContentPlaceHolder控件上调用它:

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

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

注意:将上述内容视为伪代码。我没有在任何地方实现它,所以可能(可能)需要调整才能表现得非常正确。