HTML-контроль, отображаемый с помощью шаблонных серверных элементов управления CompositeControl

Я создаю свой первый пользовательский серверный элемент управления, который наследуется от CompositeControl

Причиной контроля является возможность иметь согласованную область содержимого (элементы HTML) для нескольких онлайн-приложений, которые мы разрабатываем.

Поэтому вместо того, чтобы постоянно печатать:

<div class="titleBar">
</div>
<div class="actionBar">
</div>
<div class="workspace">
</div>

разработчик может добавить серверный элемент управления следующим образом:

<custom:Workspace id="..." runat="server" Title="MyTitle">
   <TitleBar>
      Here is the title
   </TitleBar>
   <ActionBar>
      <asp:button id="..." runat="server" Title="MyButton" />
   </ActionBar>
   <Content>
      <asp:DataGrid id="..." runat="server" />
   </Content>
</custom:Workspace>

Я прочитал статью на http://msdn.microsoft.com/en-us/library/ms178657.aspx и она работает, но проблема в том... Я не понимаю, почему. (Есть ли у кого-нибудь ссылка на версию статьи непрофессионала, в которой описано, как создавать серверные элементы управления такого типа?)

Главное, что я заметил до сих пор, это то, что Asp.net рендерит кучу элементов SPAN, что, конечно, мне не нужно.

Как можно контролировать HTML, который выводит новый CompositeControl?

Спасибо жак

PS. Вот мой код до сих пор:

using System;
using System.ComponentModel;
using System.Drawing;
using System.Security.Permissions;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.Design;
namespace TemplatedServerControl
{
    [DefaultProperty("Title")]
    [ToolboxData("<{0}:Workspace runat=server></{0}:Workspace>")]
    public class Workspace : CompositeControl
    {
        #region FIELDS
        private ITemplate _TitleBarTemplateValue;
        private ITemplate _ActionBarTemplateValue;
        private TemplateOwner _TitleBarOwnerValue;
        private TemplateOwner _ActionBarOwnerValue;
        #endregion
        #region PROPERTY - TitleBarOwner
        [Browsable(false),
        DesignerSerializationVisibility(
        DesignerSerializationVisibility.Hidden)]
        public TemplateOwner TitleBarOwner
        {
            get
            {
                return _TitleBarOwnerValue;
            }
        } 
        #endregion
        #region PROPERTY - ActionBarOwner
        [Browsable(false),
        DesignerSerializationVisibility(
        DesignerSerializationVisibility.Hidden)]
        public TemplateOwner ActionBarOwner
        {
            get
            {
                return _ActionBarOwnerValue;
            }
        }
        #endregion
        #region PROPERTY - Title
        [Bindable(true)]
        [Category("Appearance")]
        [DefaultValue("[Provide the title for the workspace]")]
        [Localizable(true)]
        public string Title
        {
            get
            {
                String s = (String)ViewState["Title"];
                return ((s == null) ? "[" + this.ID + "]" : s);
            }

            set
            {
                ViewState["Text"] = value;
            }
        }
        #endregion
        #region PROPERTY - TitleBar
        [Browsable(false),
        PersistenceMode(PersistenceMode.InnerProperty),
        DefaultValue(typeof(ITemplate), ""),
        Description("Control template"),
        TemplateContainer(typeof(Workspace))]
        public virtual ITemplate TitleBar
        {
            get
            {
                return _TitleBarTemplateValue;
            }
            set
            {
                _TitleBarTemplateValue = value;
            }
        }
        #endregion
        #region PROPERTY - ActionBar
        [Browsable(false),
        PersistenceMode(PersistenceMode.InnerProperty),
        DefaultValue(typeof(ITemplate), ""),
        Description("Control template"),
        TemplateContainer(typeof(Workspace))]
        public virtual ITemplate ActionBar
        {
            get
            {
                return _ActionBarTemplateValue;
            }
            set
            {
                _ActionBarTemplateValue = value;
            }
        }
        #endregion
        #region METHOD - CreateChildControls()
        protected override void CreateChildControls()
        {
            //base.CreateChildControls();
            Controls.Clear();

            _TitleBarOwnerValue = new TemplateOwner();
            _ActionBarOwnerValue = new TemplateOwner();

            ITemplate temp1 = _TitleBarTemplateValue;
            ITemplate temp2 = _ActionBarTemplateValue;

            temp1.InstantiateIn(_TitleBarOwnerValue);
            temp2.InstantiateIn(_ActionBarOwnerValue);

            this.Controls.Add(_TitleBarOwnerValue);
            this.Controls.Add(_ActionBarOwnerValue);
        } 
        #endregion
        #region METHOD - RenderContents(HtmlTextWriter writer)
        protected override void RenderContents(HtmlTextWriter writer)
        {
            base.RenderContents(writer);
        } 
        #endregion
    }

    [ToolboxItem(false)]
    public class TemplateOwner : WebControl
    {
    }
}

2 ответа

Решение

Экстра <span> элементы приходят из TemplateOwner контролирует, потому что WebControl (который TemplateOwner наследует от) оказывает <span> теги по умолчанию. Вы могли бы изменить TemplateOwner чтобы указать тег для отображения:

public class TemplateOwner : WebControl
{
    public TemplateOwner() :
        base(HtmlTextWriterTag.Div)
    {
    }
}

Но вам не нужно создавать свой собственный класс для использования шаблонов. Например, вы можете просто использовать Panel управления:

private Panel _TitleBarPanel;
private Panel _ActionBarPanel;

protected override void CreateChildControls()
{
    _TitleBarPanel = new Panel { CssClass = "titleBar" };
    _TitleBarTemplateValue.InstantiateIn(_TitleBarPanel);
    this.Controls.Add(_TitleBarPanel);

    _ActionBarPanel = new Panel { CssClass = "actionBar" };
    _ActionBarTemplateValue.InstantiateIn(_ActionBarPanel);
    this.Controls.Add(_ActionBarPanel);
}

Более простое решение - использовать элемент управления PlaceHolder. Как и CompositeControl, это контейнерный элемент управления. Однако, в отличие от CompositeControl, он вообще не отображает никакой контент - без содержимого или тегов.

Это означает, что вы не можете ссылаться на весь элемент управления программно, как вы можете с помощью CompositeControl, но в зависимости от того, что вы делаете, это может не понадобиться.

Каждый субконтроль будет иметь уникальный идентификатор, поэтому вы можете ссылаться на дочерние элементы управления программно (иметь дело с событиями и т. Д.)

Другие вопросы по тегам