ASP.NET 自定义/用户控件及其子控件

11

我想创建一个具有子元素的自定义/用户控件。

例如,我希望我的控件具有以下标记:

<div runat="server" id="div">
    <label runat="server" id="label"></label>
    <div class="field">
        <!-- INSERT CHILDREN HERE -->
    </div>
</div>

当我想在页面上使用它时,我只需要:

<ctr:MyUserControl runat="server" ID="myControl">
    <span>This is a child</span>
    <div runat="server" id="myChild">And another <b>child</b>
</ctr:MyUserControl>

如何将用户控件中的子控件插入到用户控件中的某个位置?可以使用类似于 asp:PlaceHolder 的功能,但我希望添加更多选项以及其他标记。此外,页面仍然需要能够访问子控件。(在上面的示例中,页面应该具有 myChild 控件)

编辑 ------

只要允许我引用页面上的子控件,它可以是模板控件。


@GenericTypeTea:那个问题讨论了如何使用模板控件,而Bob特别问的是如何在没有使用模板控件的情况下实现。 - Roman
实际上,您在模板中所做的正是我想要的。我在<div class="field">内放置了一个asp:PlaceHolder,并在其中实例化了Content模板。由于模板实例(第一次尝试时我错过了它)存在,因此我仍然可以通过页面引用子控件。 - Bob Fincheimer
我恢复了我的回答。很高兴它有帮助。 - djdd87
3个回答

7

我之前也问过类似的问题。请参见这里

我认为你需要使用ITemplate作为InnerProperty:

[PersistenceMode(PersistenceMode.InnerProperty)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
[TemplateInstance(TemplateInstance.Single)]
public ITemplate Content
{
    get
    {
        return _content;
    }
    set
    {
        _content = value;
    }
}
private ITemplate _content;

然后覆盖控件的CreateChildControls方法:

protected override void CreateChildControls()
{
   if (this.Content != null)
   {
      this.Controls.Clear();
      this.Content.InstantiateIn(this);
   }
   base.CreateChildControls();
}

使用ITemplate有何害处?你可以将其与现有标记结合使用,并在Content属性中编写所需的任何HTML。


0

我知道这个答案有点旧了,但我有一个问题,在这里没有提到。

我尝试了这个解决方案,如果内容是默认的aspx控件或纯html标记,则可以很好地工作。当我放置自定义Web控件时,我在自定义Web控件中遇到了NullReferenceException问题(子控件全部为空)。我重载了OnInit方法(在自定义Web控件代码后面),以调用EnsureChildControls(),但子控件仍未实例化。您有任何想法或建议吗?

这是我用来实例化控件的代码:

        this._pnlButtons.Controls.Add( _lbtnOkHidden );
        this._pnlButtons.Controls.Add( _lgbtnOk );

        this._pnlPopup.Controls.Add( _pnlHeader );
        this._pnlPopup.Controls.Add( _pnlContent );
        this._pnlPopup.Controls.Add( _pnlButtons );

        if ( this.Content != null )
            this.Content.InstantiateIn( _pnlContent );

        this._updatePanel.ContentTemplateContainer.Controls.Add( _lbShowPopup );
        this._updatePanel.ContentTemplateContainer.Controls.Add( _lbtnShowPopupHidden );
        this._updatePanel.ContentTemplateContainer.Controls.Add( _pnlPopup );
        this._updatePanel.ContentTemplateContainer.Controls.Add( _modalExtender );

        this.Controls.Add(_updatePanel);
        base.CreateChildControls();

我已经找到了问题所在。它与Web控件注册指令有关。这里有描述:http://t.co/wHIeY5TniV - tkestowicz
您是否有其他解决方案的链接?提供的那个不起作用。 - LairdPleng

0

另一种方法是查看 Panel 控件的源代码(例如使用 Reflector)。它似乎只是覆盖了 RenderBeginTagRenderEndTag 方法(以及其他方法来添加属性等),并将其余的渲染工作委托给 WebControl 类。


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