带模板的 UserControl,更改服务器控件呈现的 ID
UserControl with templates, change server-control rendered ID
TL;DR...
使用一次性模板创建 [UserControl]
时,是否可以将服务器端控件放置在这些模板中以呈现其 id
而无需 UserControl
或容器 ID?
在我的 ASP.NET 网络应用程序中,我创建了一个带有多个一次性模板的 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>
当 <asp:Button>
呈现给 HTML 时,元素的 id
会导致...
id="ctl00_content_muc1_ctl00_btnMyButton"
...其中第二个 ctl00
是 MyUserCtrlLiteralContainer
实例的 ID。
有没有办法让控件的id
渲染成下面这样? (所以没有使用容器的ID)
ctl00_content_muc1_btnMyButton
或者更好的是,有什么办法可以让控件的id
渲染成下面这样吗? (所以用户控件和容器的ID都没有被使用)
ctl00_content_btnMyButton
或者,是否有不同的方法来实例化 UserControl
中的控件,这会导致上述任一情况?
我不相信您能够让 ID 看起来像您希望的那样,因为它们被设计为显示控制层次结构,尽管它们很丑陋。
您可以,但是如果您愿意,可以在控件、页面或整个项目上使用静态 ID。回顾 2010 年这篇方便的 ScottGu 文章:
您要查找的部分是 Today’s Cleaner Markup Topic: Client IDs
按钮 id
包括 muc1
和 ctl00
,因为 UserControl 和 MyUserCtrlLiteralContainer 实现了 INamingContainer。如果您不希望 id
包含这些部分,但您 do 希望 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
。
TL;DR...
使用一次性模板创建 [UserControl]
时,是否可以将服务器端控件放置在这些模板中以呈现其 id
而无需 UserControl
或容器 ID?
在我的 ASP.NET 网络应用程序中,我创建了一个带有多个一次性模板的 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>
当 <asp:Button>
呈现给 HTML 时,元素的 id
会导致...
id="ctl00_content_muc1_ctl00_btnMyButton"
...其中第二个 ctl00
是 MyUserCtrlLiteralContainer
实例的 ID。
有没有办法让控件的id
渲染成下面这样? (所以没有使用容器的ID)
ctl00_content_muc1_btnMyButton
或者更好的是,有什么办法可以让控件的id
渲染成下面这样吗? (所以用户控件和容器的ID都没有被使用)
ctl00_content_btnMyButton
或者,是否有不同的方法来实例化 UserControl
中的控件,这会导致上述任一情况?
我不相信您能够让 ID 看起来像您希望的那样,因为它们被设计为显示控制层次结构,尽管它们很丑陋。
您可以,但是如果您愿意,可以在控件、页面或整个项目上使用静态 ID。回顾 2010 年这篇方便的 ScottGu 文章:
您要查找的部分是 Today’s Cleaner Markup Topic: Client IDs
按钮 id
包括 muc1
和 ctl00
,因为 UserControl 和 MyUserCtrlLiteralContainer 实现了 INamingContainer。如果您不希望 id
包含这些部分,但您 do 希望 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
。