代码之家  ›  专栏  ›  技术社区  ›  Herman Cordes

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

  •  9
  • Herman Cordes  · 技术社区  · 16 年前

    <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控件,它确实可以工作,那么为什么不工作呢?我做错什么了?甚至可以在一个控件中有两个控件集合吗?我应该以不同的方式呈现它吗?

    谢谢你的回复。

    2 回复  |  直到 16 年前
        1
  •  2
  •   Kaerber    16 年前

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

        2
  •  1
  •   David Gardiner    16 年前

    我不确定那是否行得通。但是,如果使用模板,则可以使控件正确呈现输出。

    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);
      }
    
    }
    
    推荐文章