之前已经问过这个问题
但是再次问它并没有坏处:
如何在ASP.net中为
UserControl
添加模板?
从新的UserControl
5 开始,我将其称为Contoso
:
public partial class Contoso: System.Web.UI.UserControl
{
}
这将允许我们使用新控件: 1
<Contoso>
Stuff in here
<Contoso>
创建ContentTemplate
类型的公共ITemplate
属性:
public partial class Contoso: System.Web.UI.UserControl
{
public ITemplate ContentTemplate { get; set; }
}
并向ContentTemplate
属性添加不确定数量的属性: 2
//[ParseChildren(true)]
[ParseChildren(true, "ContentTemplate")]
//[ParseChildren(false)]
public partial class Contoso: System.Web.UI.UserControl
{
[TemplateContainer(typeof(ContentContainer))]
[TemplateInstance(TemplateInstance.Single)]
[PersistenceMode(PersistenceMode.InnerProperty)]
//[PersistenceMode(PersistenceMode.InnerDefaultProperty)]
[Browsable(true)]
//[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
//[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public ITemplate ContentTemplate { get; set; }
}
这将允许我们在我们的aspx文件中向控件添加<ContentTemplate>
: 1
<Contoso>
<ContentTemplate>
Stuff in here
</ContentTemplate>
</Contoso>
接下来,我们需要实际使用 ContentTemplate
内容,将其添加到某处。我们将它添加到UserControl的一个内部div
元素中。
从最初为空的.aspx
文件开始:
<%@ Control Language="C#" AutoEventWireup="true" CodeFile="Contoso.aspx.cs" Inherits="Contoso" %>
我们添加了一个包含div
内容的父ContentTemplate
:
<%@ Control Language="C#" AutoEventWireup="true" CodeFile="Contoso.aspx.cs" Inherits="Contoso" %>
<div id="ContentDiv" runat="server"></div>
然后我们在控件的 Init 期间将ContentTemplate
内容填充到父div
中:
public partial class Contoso: System.Web.UI.UserControl
{
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
//If there's content, then put it into our ContentDiv div
if (this.ContentTemplate != null)
this.ContentTemplate.InstantiateIn(ContentDiv);
}
[PersistenceModeAttribute(PersistenceMode.InnerProperty)]
[TemplateInstanceAttribute(TemplateInstance.Single)]
[Browsable(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public ITemplate ContentTemplate { get; set; }
}
修改:表明您的班级实施INamingContainer
:
public partial class Contoso: System.Web.UI.UserControl: INamingContainer
{
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
//If there's content, then put it into our ContentDiv div
if (this.ContentTemplate != null)
this.ContentTemplate.InstantiateIn(ContentDiv);
}
[PersistenceModeAttribute(PersistenceMode.InnerProperty)]
[TemplateInstanceAttribute(TemplateInstance.Single)]
[Browsable(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public ITemplate ContentTemplate { get; set; }
}
INamingContainer
界面没有任何成员,仅用于将您的UserControl
类标记为某种内容。
我们已经完成 3 。我们现在可以在aspx页面中使用此控件。但首先我们需要在aspx页面的顶部“注册”:
<%@ Register src="Contoso.ascx" TagName="Contoso" tagprefix="uc" %>
其中:
Contoso.ascx
是ascx
文件的名称Contoso
是我们将用于引用此用户控件的元素的名称uc
是我们必须放在uc:Contoso
前面的一些文字(我使用uc
作为用户控件的缩写)将控件添加到我们的页面:
<uc:Contoso ID="Crackers" runat="server">
<ContentTemplate>
Stuff goes here
</ContentTemplate>
</qwerty:Contoso>
我们已经完成了! 4
修改:忘记添加上述原因不起作用的原因。 Visual Studio显示错误:
创建控件时出错 - 破解者
类型'System.Web.UI.UserControl'没有名为'ContentTemplate'的公共属性
这是有道理的,因为UserControl
没有名为ContentTemplate
的公共属性 - 所以我几乎不能责怪它。
这个问题是正在进行的Stackoverflow系列中的一个,“模板化用户控件”:
答案 0 :(得分:12)
嗯,我相信你差不多了。
顺便说一句。 UserControl不使用Visual Studio Designer呈现,但是当您运行应用程序时,控件可以正常工作。如果您使用服务器控件,则会有所不同,在这种情况下,控件在Visual Studio设计器中正确显示
以下代码非常适合构建模板化用户控件和模板化服务器控件但是,如果您想添加绑定功能,则过程略有不同,take a look
UserControl
。
public class MyTemplateContainer : Control, INamingContainer { }
protected void Page_Load(object sender, EventArgs e)
{
// just to demonstrate using the contorl
this.WebUserControl1.Controls.Add(new LiteralControl("<br />new control"));
}
<%@ Register src="WebUserControl.ascx" tagname="WebUserControl" tagprefix="uc1" %>
<uc1:WebUserControl ID="WebUserControl1" runat="server">
<ContentTemplate>
My Template<br />
<asp:Label Text='Hello People' runat="server" ID="lblMessage" />
</ContentTemplate>
</uc1:WebUserControl>
public partial class WebUserControl : System.Web.UI.UserControl
{
[TemplateContainer(typeof(MyTemplateContainer))]
[TemplateInstance(TemplateInstance.Single)]
[PersistenceMode(PersistenceMode.InnerProperty)]
[Browsable(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public ITemplate ContentTemplate { get; set; }
protected void Page_Init(object sender, EventArgs e)
{
this.myPlaceHolderTag.Controls.Clear();
if (this.ContentTemplate != null)
{
var container = new MyTemplateContainer();
this.ContentTemplate.InstantiateIn(container);
this.myPlaceHolderTag.Controls.Add(container);
}
else
{
this.myPlaceHolderTag.Controls.Add(new LiteralControl("No template defined"));
}
}
}
<%@ Control Language="C#" AutoEventWireup="true" CodeFile="WebUserControl.ascx.cs" Inherits="WebUserControl" %>
<asp:PlaceHolder runat="server" ID="myPlaceHolderTag" />
<%@ Register Namespace="MyControls" TagPrefix="my" %>
<my:MyServerControl runat="server" ID="myServerControl">
<ContentTemplate>
My Server templated control<br />
<asp:Label Text="My Label" runat="server" />
</ContentTemplate>
</my:MyServerControl>
namespace MyControls
{
[ToolboxItem(false)]
public class MyTemplateContainer : Control, INamingContainer { }
}
namespace MyControls
{
[ToolboxData("<{0}:MyServerControl runat=server >")]
[ToolboxItem(true)]
[ParseChildren(true)]
// you can inherit from another control if you like, for example from the CompositeControl
public class MyServerControl : Control, INamingContainer
{
[TemplateInstance(TemplateInstance.Multiple)]
[TemplateContainer(typeof(MyTemplateContainer))]
[PersistenceMode(PersistenceMode.InnerProperty)]
[Browsable(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
[DefaultValue(null)]
public ITemplate ContentTemplate { get; set; }
protected override void CreateChildControls()
{
var p = new Panel { ID = "myPanel", BackColor = Color.Silver, Width = new Unit("100%") };
if (this.ContentTemplate == null)
{
p.Controls.Add(new LiteralControl("No content has been specified"));
}
else
{
var c = new MyTemplateContainer();
this.ContentTemplate.InstantiateIn(c);
p.Controls.Add(c);
}
this.Controls.Clear();
this.Controls.Add(p);
}
public override void DataBind()
{
this.CreateChildControls();
this.ChildControlsCreated = true;
base.DataBind();
}
public override ControlCollection Controls
{
get
{
this.EnsureChildControls();
return base.Controls;
}
}
}
}
参考文献: