Подтвердить что ты не робот

Как добавить шаблон в UserControl?

Этот вопрос задан раньше

но это не помешает снова спросить:

Как добавить шаблон в UserControl в ASP.net?

Что еще не работает

  • Начните с нового 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; }
    }
    

    это позволит нам добавить <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" %>
    

    добавим родительский div, который будет содержать наш ContentTemplate материал:

    <%@ Control Language="C#" AutoEventWireup="true" CodeFile="Contoso.aspx.cs" Inherits="Contoso" %>
    <div id="ContentDiv" runat="server"></div>
    

    Затем мы наполняем материал ContentTemplate в этот родительский div во время управления Init:

    public partial class Contoso: System.Web.UI.UserControl
    {
       protected override void OnInit(EventArgs e)
       {
          base.OnInit(e);
    
          //If there 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 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 показывает ошибку:

Ошибка создания Control - Crackers

Тип 'System.Web.UI.UserControl' не имеет открытого свойства с именем 'ContentTemplate'

enter image description here

Это имеет смысл, поскольку UserControl не имеет открытого свойства с именем ContentTemplate - поэтому я вряд ли могу его обвинить.

Серия

Этот вопрос является одним из текущих серий Stackoverflow, "Шаблоны пользовательских элементов управления" :

Чтение бонусов

Сноски

  • 1 Вы никогда не сможете использовать этот синтаксис. Это просто читаемая и понятная форма.
  • 2 Никто не знает, какие атрибуты добавить или почему. Добавьте более или менее атрибут по вкусу.
  • 3 Не сделано. Выполнено с UserControl, но не наша работа.
  • 4 Не сделано; он не работает.
  • 5 на веб-сайте (а не в веб-приложении, а не в отдельной сборке)
4b9b3361

Ответ 1

Ну, я думаю, вы почти получили его.

BTW. UserControl не отображается с помощью Visual Studio Designer, однако при запуске приложения работает элемент управления. Это отличается, если вы используете серверные элементы управления, в этом случае элемент управления отображается правильно в дизайнере Visual Studio

Следующий код отлично подходит для создания шаблонных пользовательских элементов управления и шаблонных элементов управления сервером, однако, если вы хотите добавить возможности привязки, процесс немного отличается, посмотрите

Загрузить исходный код

Это код для создания шаблона UserControl.

Простой выход

enter image description here

Контейнер шаблонов

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" />

Код для добавления шаблонного управления сервером

Выход

enter image description here

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

Литература: