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 属性,“内容”和“页脚”。从未尝试构建具有多个控件集合的控件,但像这样解决了它(简化):

[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”的控件。

有点可以理解,因为标签出现在 controlcollection 中的文本框之前。但是,使用默认的 asp.net 控件它确实可以工作,那么为什么这不起作用呢?我究竟做错了什么?甚至可以在一个控件中有两个控件集合吗?我应该以不同的方式渲染它吗?

感谢您的回复。

4

2 回答 2

2

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

于 2010-03-25T08:53:43.237 回答
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);
  }

}
于 2010-03-19T05:25:31.773 回答