【问题标题】:How can I render content from an aspx page in a custom control如何在自定义控件中呈现来自 aspx 页面的内容
【发布时间】:2021-09-01 18:56:54
【问题描述】:

我正在编写一个复合控件,它应该呈现放置在使用 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 没有被渲染。我已经查看了这个链接Building Templated Custom ASP.NET Serv Controls,但我不知道这是否适用或如何在我的情况下应用它。如果您查看链接,您会看到 &lt;StatsTemplate&gt; 标记内的 HTML 元素在自定义控件中呈现。

【问题讨论】:

  • 在您的MyComposite 类中,您似乎没有使用UserContentTemplate 属性。那是你的问题。
  • @Dai,这确实是问题所在。我不知道如何使用该属性。该属性现在所做的就是将UserContentTemplate 标记公开给aspx 页面上的消费者。那么你知道如何渲染UserContentTemplate标签中包含的内容吗?

标签: c# asp.net vb.net custom-server-controls


【解决方案1】:

我在这里找到了答案:Web Control Templates ExplainedMiguel 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. 创建一个从CompositeControl实现 INamingContainer继承的类 (MyTemplate)
  2. TemplateContainer类型的MyTemplate属性装饰UserContentTemplate
  3. CreateChildControls 中实例化UserContentTemplate
  4. 渲染所有Render覆盖中的控件
  5. 删除 DataBind 覆盖,我不需要它

UserContentTemplate 将在 aspx 页面中使用 UserContentTemplate 标记后立即实例化。

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

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

【讨论】:

    【解决方案2】:

    HTML of 下面的函数返回渲染控件的 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
    

    【讨论】:

    • 感谢@Chris Berlin,您的解决方案如何适应全局?我从哪里打电话给RenderUserControlToString?我会将这个函数放在MyComposite 类中并将Me 作为WebControl 参数传递吗?我对返回值做些什么吗?虽然我已经回答了我的问题,但我对使用自定义服务器控件的其他方式很感兴趣。
    猜你喜欢
    • 1970-01-01
    • 2012-02-07
    • 2011-09-20
    • 2011-01-30
    • 2011-01-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-24
    相关资源
    最近更新 更多