UserControl with templates,更改服务器控件呈现的ID

时间:2017-07-05 19:20:50

标签: c# asp.net vb.net user-controls

TL; DR ...

使用一次性模板创建[UserControl]时,是否可以在这些模板中放置服务器端控件来呈现id 而不用 {{1或容器ID?

在我的ASP.NET Web应用程序中,我创建了一个带有多个一次性模板的UserControl(我这里仅为其中一个模板提供了代码)...

UserControl

(注意,Public Class MyUserCtrl Inherits System.Web.UI.UserControl Private Class MyUserCtrlLiteralContainer Inherits Control Implements INamingContainer End Class <TemplateContainer(GetType(MyUserCtrlLiteralContainer)), TemplateInstance(TemplateInstance.Single), PersistenceMode(PersistenceMode.InnerProperty)> Public Property FirstTemplate As ITemplate Private Sub Page_Init(ByVal sender As Object, ByVal e As EventArgs) Handles MyBase.Init If FirstTemplate IsNot Nothing Then Dim container As New MyUserCtrlLiteralContainer() FirstTemplate.InstantiateIn(container) plhFirst.Controls.Add(container) End If End Sub End Class 是标记中的plhFirst

这是页面中使用的控件的示例(由<asp:PlaceHolder>页面控制)...

Master

<asp:Content runat="server" ID="content" ContentPlaceHolderID="mainContent"> <uc1:MyUserCtrl runat="server" id="muc1"> <FirstTemplate> <asp:Button runat="server" id="btnMyButton" /> </FirstTemplate> </uc1:MyUserCtrl> </asp:Content> 呈现给HTML时,元素的<asp:Button>会导致......

id

...其中第二个id="ctl00_content_muc1_ctl00_btnMyButton" ctl00个实例的ID。

有没有办法使控件渲染的MyUserCtrlLiteralContainer如下所示? (因此不使用容器的ID)

id

甚至更好,有没有办法使控件渲染的ctl00_content_muc1_btnMyButton 如下所示? (因此,既不使用usercontrol或容器的ID)

id

或者,是否有一种不同的方法可以实例化导致上述任何一种情况的ctl00_content_btnMyButton 中的控件?

2 个答案:

答案 0 :(得分:1)

按钮id包括muc1ctl00,因为UserControl和MyUserCtrlLiteralContainer实现了INamingContainer。如果您不希望id包含这些部分,但执行希望id包含其他祖先ID,则您无法使用这些控件类型。

删除ctl00除非您特别需要自定义容器控件,否则可以删除MyUserCtrlLiteralContainer并直接在PlaceHolder中实例化模板。

删除muc1您必须将UserControl重写为不实现INamingContainer的服务器控件。

以下是一个示例实现:

<ParseChildren(True)>
Public Class MyUserCtrl
    Inherits Control

    Private plhFirst As PlaceHolder

    <TemplateInstance(TemplateInstance.Single),
     PersistenceMode(PersistenceMode.InnerProperty)>
    Public Property FirstTemplate As ITemplate

    Private Sub Page_Init(sender As Object, e As EventArgs) Handles MyBase.Init
        plhFirst = New PlaceHolder()
        Controls.Add(plhFirst)

        If FirstTemplate IsNot Nothing Then
            FirstTemplate.InstantiateIn(plhFirst)
        End If
    End Sub

    Protected Overrides Sub Render(writer As HtmlTextWriter)
        ' <div class="myUserCtrl">
        writer.AddAttribute(HtmlTextWriterAttribute.Class, "myUserCtrl")
        writer.RenderBeginTag(HtmlTextWriterTag.Div)

        ' <div class="firstControls">
        writer.AddAttribute(HtmlTextWriterAttribute.Class, "firstControls")
        writer.RenderBeginTag(HtmlTextWriterTag.Div)

        plhFirst.RenderControl(writer)

        ' </div>
        writer.RenderEndTag()

        ' </div>
        writer.RenderEndTag()
    End Sub
End Class

注意:为避免可能的ID冲突,我故意让plhFirst.ID未设置。

答案 1 :(得分:0)

我不相信你能够按照自己的意愿获取ID,因为它们的设计目的是为了显示控制层次结构,而且非常丑陋。

可以,但是如果您愿意,可以在控件,页面或整个项目中使用静态ID。回顾一下2010年的这篇方便的ScottGu文章:

https://weblogs.asp.net/scottgu/cleaner-html-markup-with-asp-net-4-web-forms-client-ids-vs-2010-and-net-4-0-series

您要查找的部分是{{1}}