如何在自定义控件中呈现 aspx 页面中的内容

How can I render content from an aspx page in a custom control

我正在编写一个复合控件,它应该在使用的 aspx 页面中呈现放置在它的开始和结束标记之间的任何内容。

VB

Public Class MyComposite
    Inherits CompositeControl
    Implements INamingContainer

    Public Property UserContentTemplate as ITemplate = Nothing

    Public Overrides ReadOnly Property Controls() As ControlCollection
        Get
            EnsureChildControls()
            Return MyBase.Controls
        End Get
    End Property

    Protected Overrides Sub CreateChildControls()
        ' This is where I'm creating the controls
        ' for the composite
    End Sub

    Protected Overrides Sub Render(ByVal writer As HtmlTextWriter)
        ' This is where I render the composite controls
    End Sub

    Protected Overrides Sub RecreateChildControls()
        EnsureChildControls()
    End Sub

    Public Overrides Sub DataBind()
        CreateChildControls()
        ChildControlsCreated = True
        MyBase.DataBind()
    End Sub
End Class

从这里开始,UserContentTemplate 在消费 aspx 页面中可用

<cc:MyComposite runat="server" ID="MyCompositeID">
    <UserContentTemplate>
        <asp:Button... />
        <asp:TextBox... />
    </UserContentTemplate>
</cc:MyComposite>

此时,asp:Buttonasp:TextBox 没有被渲染。我已经查看了这个 link Building Templated Custom ASP.NET Serv Controls,但我不知道这是否适用或如何在我的情况下应用它。如果您查看 link,您会看到 <StatsTemplate> 标记内有 HTML 元素,这些元素在自定义控件中呈现。

HTML 的以下函数 returns 渲染控件的 HTML。

您可以使用占位符添加所有用于渲染的控件并将占位符传递给函数,或者您可以直接传递您的控件。

 Public Function RenderUserControlToString(ByRef WebControl As Control) As String

        Dim sb As StringBuilder = New StringBuilder
        Dim sw As StringWriter = New StringWriter(sb)
        Dim htw As HtmlTextWriter = New HtmlTextWriter(sw)
        Try
            WebControl.RenderControl(htw)
        Catch ex As Exception
            sb.Append(ex.Message & vbCrLf & ex.StackTrace)
        End Try
        Return sb.ToString()
    End Function

我在这里找到了答案:Web Control Templates Explained written by Miguel Castro。这篇文章有助于阐明我在问题中引用的 Microsoft 文章中发生的事情。

Imports System.Web.UI
Imports System.Web.UI.WebControls

Public Class MyTemplate
    Inherits CompositeControl
    Implements INamingContainer
End Class

Public Class MyComposite
    Inherits CompositeControl
    Implements INamingContainer

    <
        TemplateContainer(GetType(MyTemplate)),
        PersistenceMode(PersistenceMode.InnerProperty)
    > _
    Public Property UserContentTemplate as ITemplate = Nothing

    Public Overrides ReadOnly Property Controls() As ControlCollection
        Get
            EnsureChildControls()
            Return MyBase.Controls
        End Get
    End Property

    Protected Overrides Sub CreateChildControls()
        ' I prepend the template to the Controls collection
        If UserContentTemplate IsNot Nothing Then
            Dim template = New MyTemplate()
            UserContentTemplate.InstantiateIn(template)
            Controls.Add(template)
        End If
 
        ' Create and add other controls here
    End Sub

    Protected Overrides Sub Render(ByVal writer As HtmlTextWriter)
        ' This is where I render the composite controls
        writer.AddAttribute(HtmlTextWriterAttribute.Class, "my-class")
        writer.RenderBeginTag(TagKey)

        For Each ctl As Control In Controls
            ctl.RenderControl(writer)
        Next

        writer.RenderEndTag()
    End Sub

    Protected Overrides Sub RecreateChildControls()
        EnsureChildControls()
    End Sub
End Class

要点

  1. 创建一个 class (MyTemplate) 继承 来自 CompositeControl 实现 INamingContainer
  2. 用类型为 MyTemplate
  3. TemplateContainer 属性修饰 UserContentTemplate
  4. CreateChildControls
  5. 中实例化UserContentTemplate
  6. 渲染所有 Render覆盖
  7. 中的控件
  8. 删除 DataBind 覆盖,我不需要它

一旦在 aspx 页面中使用 UserContentTemplate 标记,就会实例化 UserContentTemplate

<cc:MyComposite runat="server" ID="MyCompositeID">
    <UserContentTemplate>
        <asp:Button... />
        <asp:TextBox... />
    </UserContentTemplate>
</cc:MyComposite>

此答案中的代码解决了能够使用模板在复合控件中呈现消费者(开发人员)内容的问题。