asp.net – 如何添加一个模板到一个UserControl?

这个问题之前已经提过

> Web Forms :: Design Time Support For Custom Templated User Control In VS 2008
> VS 2008 Using the ITemplate in a UserControl and getting a design time rendoring error
> how to show the controls for web user control in design time?
> UserControl ITemplate Property Design Time Error – Easy for a Guru…

但不要再问这个问题:

How do i add templating to a UserControl in ASP.net?

到目前为止还没有工作

>从一个新的UserControl5开始,我会调用Contoso:

public partial class Contoso: System.Web.UI.UserControl
{
}

这将允许我们使用一个新的控件:1

<Contoso>
    Stuff in here
<Contoso>

>创建类型为ITemplate的公共ContentTemplate属性

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; }
}

这将允许我们添加< ContentTemplate>到我们的aspx文件中的控件:1

<Contoso>
   <ContentTemplate>
       Stuff in here
   </ContentTemplate>
</Contoso>

>接下来我们需要实际使用ContentTemplate的东西,把它添加到某个地方。我们通过将其添加到我们的UserControl的一个内部div元素中来实现。

从我们原来为空的.aspx文件开始:

<%@ Control Language="C#" AutoEventWireup="true" CodeFile="Contoso.aspx.cs" Inherits="Contoso" %>

我们添加一个将保留ContentTemplate内容的父div:

<%@ 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>

我们完成了!

编辑:忘记添加上述原因不行。 Visual Studio显示错误

Error Creating Control – Crackers

Type ‘System.Web.UI.UserControl’ does not have a public property named ‘ContentTemplate’

这是有道理的,因为UserControl没有名为ContentTemplate的公共属性 – 所以我很难怪它。

系列

这个问题是正在进行的Stackoverflow系列“模板用户控件”中的一个

> How to add a Templating to a UserControl?
> How to inherit from Control,rather than UserControl?
> UserControl has IsPostBack,but Control does not
> UserControl does not have public property named ContentTemplate
> How do i specify CodeFileBaseClass from web.config?

奖金阅读

> How to: Create Templated ASP.NET User Controls
> Creating a Templated User Control with ASP.Net 2.0
> Templated User Controls in ASP.NET for Better Maintainability

脚注

> 1你不能使用这种语法。这只是一个容易阅读和理解的形式。
> 2没有人知道要添加什么属性,或为什么。添加或多或少的属性来品味。
> 3未完成完成UserControl,但不是我们的工作。
> 4未完成;它不工作
> 5在网站(不是Web应用程序,不在单独的程序集)

解决方法

我相信你几乎得到了。

BTW。 UserControl不使用Visual Studio Designer呈现,但是当您运行应用程序时,该控件可以正常工作。如果您使用“服务器控件”,则在Visual Studio设计器中正确显示该控件时,这是不同的

以下代码非常适用于构建模板化用户控件和模板化服务器控件,但如果要添加绑定功能,则过程略有不同,take a look

Download Source Code

这是创建一个模板的UserControl的代码

简单输出

模板容器

public class MyTemplateContainer : Control,INamingContainer { }

ASPX代码背后

protected void Page_Load(object sender,EventArgs e)
{
    // just to demonstrate using the contorl
    this.webusercontrol1.Controls.Add(new LiteralControl("<br />new control"));
}

ASPX

<%@ 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>

ASCX代码落后

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"));
        }
    }
}

ASCX

<%@ Control Language="C#" AutoEventWireup="true" CodeFile="webusercontrol.ascx.cs" Inherits="webusercontrol" %>

<asp:PlaceHolder runat="server" ID="myPlaceHolderTag" />

添加模板服务器控件的代码

产量

ASPX

<%@ 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;
            }
        }
    }
}

参考文献:

> How to: Create Templated ASP.NET User Controls
> Building Templated Custom ASP.NET Server Controls
> Building DataBound Templated Custom ASP.NET Server Controls

相关文章

### 创建一个gRPC服务项目(grpc服务端)和一个 webapi项目(...
一、SiganlR 使用的协议类型 1.websocket即时通讯协议 2.Ser...
.Net 6 WebApi 项目 在Linux系统上 打包成Docker镜像,发布为...
一、 PD简介PowerDesigner 是一个集所有现代建模技术于一身的...
一、存储过程 存储过程就像数据库中运行的方法(函数) 优点:...
一、Ueditor的下载 1、百度编辑器下载地址:http://ueditor....