如何将Template添加到UserControl?

Ian*_*oyd 21 asp.net user-controls templating webusercontrol

之前已经问过这个问题

但再次问它并没有坏处:

如何UserControl在ASP.net中添加模板?

到目前为止还没有奏效

  1. 从一个新的UserControl5开始,我打电话给Contoso:

    public partial class Contoso: System.Web.UI.UserControl
    {
    }
    
    Run Code Online (Sandbox Code Playgroud)

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

    <Contoso>
        Stuff in here
    <Contoso>
    
    Run Code Online (Sandbox Code Playgroud)
  2. 创建一个ContentTemplate类型为的公共属性ITemplate:

    public partial class Contoso: System.Web.UI.UserControl
    {
       public ITemplate ContentTemplate { get; set; }
    }
    
    Run Code Online (Sandbox Code Playgroud)

    并向属性添加不确定数量的属性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; }
    }
    
    Run Code Online (Sandbox Code Playgroud)

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

    <Contoso>
       <ContentTemplate>
           Stuff in here
       </ContentTemplate>
    </Contoso>
    
    Run Code Online (Sandbox Code Playgroud)
  3. 接下来我们需要实际使用这些ContentTemplate东西,在某处添加它.我们通过将其添加到UserControl的一个内部div元素来实现此目的.

    从我们.aspx最初为空的文件开始:

    <%@ Control Language="C#" AutoEventWireup="true" CodeFile="Contoso.aspx.cs" Inherits="Contoso" %>
    
    Run Code Online (Sandbox Code Playgroud)

    我们添加一个div将保存我们的ContentTemplate东西的父母:

    <%@ Control Language="C#" AutoEventWireup="true" CodeFile="Contoso.aspx.cs" Inherits="Contoso" %>
    <div id="ContentDiv" runat="server"></div>
    
    Run Code Online (Sandbox Code Playgroud)

    然后我们在控件的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; }
    }
    
    Run Code Online (Sandbox Code Playgroud)
  4. 编辑:表明您的类实现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; }
    }
    
    Run Code Online (Sandbox Code Playgroud)

    INamingContainer界面没有任何成员,只用来标记你的UserControl类的东西.

  5. 我们完成了3.我们现在可以在aspx页面中使用此控件.但首先我们需要在aspx页面的顶部"注册"它:

    <%@ Register src="Contoso.ascx" TagName="Contoso" tagprefix="uc" %>
    
    Run Code Online (Sandbox Code Playgroud)

    哪里:

    • Contoso.ascxascx文件的名称
    • Contoso 是我们将用于引用此用户控件的元素的名称
    • uc是我们必须放在前面的一些文字uc:Contoso(我uc用作用户控制的简称)
  6. 将控件添加到我们的页面:

    <uc:Contoso ID="Crackers" runat="server">
        <ContentTemplate>
            Stuff goes here
        </ContentTemplate>
    </qwerty:Contoso>
    
    Run Code Online (Sandbox Code Playgroud)

我们完成了!4

编辑:忘记添加上述原因不起作用的原因.Visual Studio显示错误:

创建控件时出错 - 破解者

类型'System.Web.UI.UserControl'没有名为'ContentTemplate'的公共属性

在此输入图像描述

这是有道理的,因为UserControl没有一个名为的公共财产ContentTemplate- 所以我几乎不能责怪它.

系列

这个问题是正在进行的Stackoverflow系列中的一个,"模板化用户控件":

奖金阅读

脚注

  • 1您无法使用该语法.这只是一个易于阅读和理解的形式.
  • 2没人知道要添加什么属性,或者为什么.添加或多或少的属性品尝.
  • 3没做完.完成UserControl,但不是我们的工作.
  • 4未完成; 它不起作用.
  • 网站中的5(不是Web应用程序,不是单独的程序集)

Jup*_*aol 12

好吧,我相信你差不多了.

BTW.UserControl不使用Visual Studio Designer呈现,但是当您运行应用程序时,控件可以正常工作.如果您使用服务器控件,则会有所不同,在这种情况下,控件在Visual Studio设计器中正确显示

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

下载源代码

这是创建模板的代码UserControl.

简单的输出

在此输入图像描述

模板容器

public class MyTemplateContainer : Control, INamingContainer { }
Run Code Online (Sandbox Code Playgroud)

ASPX代码背后

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

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>
Run Code Online (Sandbox Code Playgroud)

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"));
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

ASCX

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

<asp:PlaceHolder runat="server" ID="myPlaceHolderTag" />
Run Code Online (Sandbox Code Playgroud)

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

产量

在此输入图像描述

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>
Run Code Online (Sandbox Code Playgroud)

模板容器

namespace MyControls
{
    [ToolboxItem(false)]
    public class MyTemplateContainer : Control, INamingContainer { } 
}
Run Code Online (Sandbox Code Playgroud)

模板化服务器控制

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;
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

参考文献: