简体   繁体   English

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

[英]Render multiple control collections in ASP.NET custom control

I've build a custom WebControl, which has the following structure: 我构建了一个自定义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>

The control contains two ControlCollection properties, 'Contents' and 'Footer'. 该控件包含两个ControlCollection属性,'Contents'和'Footer'。 Never tried to build a control with multiple control collections, but solved it like this (simplified): 从未尝试使用多个控件集合构建控件,但是像这样(简化)解决了它:

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

However it seems to render properly, it doesn't work anymore if I add some asp.net labels and input controls inside the property (see above asp.net code). 但是它似乎正确呈现,如果我在属性中添加一些asp.net标签和输入控件,它就不再起作用了(参见上面的asp.net代码)。 I'll get the HttpException: 我会得到HttpException:

Unable to find control with id 'KeywordTextBox' that is associated with the Label 'KeywordLabel'. 无法找到与标识'KeywordLabel'关联的id'KeywordTextBox'的控件。

Somewhat understandable, because the label appears before the textbox in the controlcollection. 有点可以理解,因为标签出现在controlcollection中的文本框之前。 However, with default asp.net controls it does work, so why doesn't this work? 但是,使用默认的asp.net控件确实可行,所以为什么这不起作用呢? What am I doing wrong? 我究竟做错了什么? Is it even possible to have two control collections in one control? 甚至可以在一个控件中有两个控件集合吗? Should I render it differently? 我应该以不同的方式呈现它

Thanks for replies. 谢谢你的回复。

You can use two Panels as parents of your two control collections (and they would provide grouping and improved readability). 您可以使用两个Panel作为两个控件集合的父级(它们可以提供分组和提高可读性)。 Add your controls from each collection to the Controls collection of respective panel, and in the Render method just call Render methods of each panel. 将每个集合中的控件添加到相应面板的Controls集合中,并在Render方法中调用每个面板的Render方法。 Panels will automatically render their children, and will provide them with their own namespace, so, you can have controls with similar IDs in different panels. 面板将自动呈现其子项,并为它们提供自己的命名空间,因此,您可以在不同的面板中使用具有类似ID的控件。

I'm not sure that will work. 我不确定这会奏效。 If you make use of templates however you can get the control to render output correctly. 如果您使用模板,则可以使控件正确呈现输出。

First, define a class to be used as the type for the container control: 首先,定义一个类作为容器控件的类型:

public class ContentsTemplate : Control, INamingContainer
{
}

And now the custom control: 而现在的自定义控件:

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

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM