在ASP.NET自定义控件中呈现多个控件集合

9
我已经构建了一个自定义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:
“找不到与标签'KeywordLabel'关联的ID为'KeywordTextBox'的控件。”
这有些可以理解,因为标签在控件集合中出现在文本框之前。然而,默认的asp.net控件确实可以工作,那么为什么这样做不行呢?我做错了什么?一个控件中是否可能有两个控件集合?我应该以不同的方式呈现它吗?
感谢回复。
2个回答

2
你可以使用两个面板作为你的两个控件集合的父级(它们将提供分组和更好的可读性)。从每个集合中添加你的控件到相应面板的控件集合中,在Render方法中只需调用每个面板的Render方法。面板将自动呈现它们的子元素,并为它们提供自己的命名空间,因此,你可以在不同面板中拥有具有相似ID的控件。

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

}

我遇到了和帖主类似的问题,这个方法行不通。因为你无法在 ITemplates 内部引用任何控件,因为它们没有实例化,这就破坏了此类型控件的目的。 - mattmanser

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接