我构建了一个自定义WebControl,它具有以下结构:
<gws:ModalBox ID="ModalBox1" HeaderText="Title" runat="server">
<Contents>
<asp:Label ID="KeywordLabel" AssociatedControlID="KeywordTextBox" runat="server">Keyword: </asp:Label><br />
<asp:TextBox ID="KeywordTextBox" Text="" runat="server" />
</Contents>
<Footer>(controls...)</Footer>
</gws:ModalBox>
该控件包含两个ControlCollection属性,'Contents'和'Footer'。从未尝试构建具有多个控件集合的控件,但是像这样(简化)解决了它:
[PersistChildren(false), ParseChildren(true)]
public class ModalBox : WebControl
{
private ControlCollection _contents;
private ControlCollection _footer;
public ModalBox()
: base()
{
this._contents = base.CreateControlCollection();
this._footer = base.CreateControlCollection();
}
[PersistenceMode(PersistenceMode.InnerProperty)]
public ControlCollection Contents { get { return this._contents; } }
[PersistenceMode(PersistenceMode.InnerProperty)]
public ControlCollection Footer { get { return this._footer; } }
protected override void RenderContents(HtmlTextWriter output)
{
// Render content controls.
foreach (Control control in this.Contents)
{
control.RenderControl(output);
}
// Render footer controls.
foreach (Control control in this.Footer)
{
control.RenderControl(output);
}
}
}
然而,它似乎正确呈现,如果我在属性中添加一些asp.net标签和输入控件,它就不再起作用了(参见上面的asp.net代码)。我会得到HttpException:
无法找到id为'KeywordTextBox'的控件 与标签'KeywordLabel'相关联。
有点可以理解,因为标签出现在controlcollection中的文本框之前。但是,使用默认的asp.net控件确实可行,所以为什么这不起作用呢?我究竟做错了什么?甚至可以在一个控件中有两个控件集合吗?我应该以不同的方式呈现它吗?
感谢您的回复。
答案 0 :(得分:2)
您可以使用两个Panel作为两个控件集合的父级(它们可以提供分组和提高的可读性)。将每个集合中的控件添加到相应面板的Controls集合中,并在Render方法中调用每个面板的Render方法。面板会自动渲染他们的子节点,并为他们提供自己的命名空间,因此,您可以在不同的面板中使用具有类似ID的控件。
答案 1 :(得分:1)
我不确定这会有效。如果您使用模板,则可以使控件正确呈现输出。
首先,定义一个用作容器控件类型的类:
public class ContentsTemplate : Control, INamingContainer
{
}
现在是自定义控件:
[PersistChildren(false), ParseChildren(true)]
public class ModalBox : CompositeControl
{
[PersistenceMode(PersistenceMode.InnerProperty)]
[TemplateContainer(typeof(ContentsTemplate))]
public ITemplate Contents { get; set; }
[PersistenceMode(PersistenceMode.InnerProperty)]
[TemplateContainer(typeof(ContentsTemplate))]
public ITemplate Footer { get; set; }
protected override void CreateChildControls()
{
Controls.Clear();
var contentsItem = new ContentsTemplate();
Contents.InstantiateIn(contentsItem);
Controls.Add(contentsItem);
var footerItem = new ContentsTemplate();
Footer.InstantiateIn(footerItem);
Controls.Add(footerItem);
}
}