使用标准子控件的自定义控件 - 为什么他们的ID为空?

时间:2014-01-05 20:32:48

标签: c# asp.net .net

我想创建一个理想的自定义控件:

<foo:Frobnicate runat="server">
    <DoStuffWithThese>
        <asp:TextBox runat="server" ID="fizzbot" />
    </DoStuffWithThese>
    <!-- other controls can be in the wrapper but outside the DoSomeStuffWithThese collection -->       
    <asp:DropDownList runat="server" ID="othercontrol" />
</foo:Frobnicate>

虽然我会在必要时解决这个问题:

<foo:Frobnicate runat="server">
    <DoStuffWithThese>
        <asp:TextBox runat="server" ID="fizzbot" />
    </DoStuffWithThese>
    <AndOtherStuffWithThese>      
        <asp:DropDownList runat="server" ID="othercontrol" />
    </AndOtherStuffWithThese>
</foo:Frobnicate>

我可以在代码隐藏中访问控件(在第二个非理想示例中),但由于某种原因,他们的ID(我需要的)是NULL

以下是代码隐藏:

[ParseChildren(true)]
public class Frobnicate : WebControl {

       [PersistenceMode(PersistenceMode.InnerProperty)]
       public List<WebControl> DoStuffWithThese { get; set; }

       [PersistenceMode(PersistenceMode.InnerProperty)]
       public List<WebControl> AndOtherStuffWithThese { get; set; }

       public override OnLoad(EventArgs e) {
         base.OnLoad(e);

         foreach(Control currentControl in DoStuffWithThese) {
           // the control can be accessed (e.g. I can see it's a TextBox, etc.
           // but currentControl.ID == null here -- why? :(
         }

}

有谁知道这是为什么?更重要的是,我如何解决它,以便我可以获得其中一种格式的自定义控件并能够访问ID?

2 个答案:

答案 0 :(得分:1)

我相信你必须在你的班级中实现INamingContainer,WebControl本身不会这样做。请注意,它只是一个标记界面,您不需要任何代码。此外,您应该使用ITemplate(它允许您实际创建控件并在控件的输出中使用它们)而不是控件列表。

这应该有用:http://msdn.microsoft.com/en-us/library/36574bf6(v=vs.85).aspx

如果这不是你想要的,请详细说明你实际上要做什么,以及为什么你不想使用模板。

要解释一下 - 只需添加对服务器控件的引用,您实际上并没有将它添加到页面/控件树的任何位置,这意味着它不是实际创建的,并且它不能作为页面的一部分,真的(包括一个有用的UniqueID / ClientID,几乎任何逻辑,除了构造函数)。

当您拥有模板时,您可以使用数据绑定来填写所需的数据等,例如,您可以使用FindControl访问控件(或者只使用Controls集合,但请注意,模板可能还包含文字和其他内容,而不仅仅是您的控件。)

答案 1 :(得分:0)

你能得到下拉列表的ID吗?如果是这样,我认为它与缺少runat = server的其他项目有关。