Управляющий 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
    {
    }
}

person Jacques    schedule 04.04.2012    source источник


Ответы (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);
}
person Michael Liu    schedule 04.04.2012
comment
Спасибо, Майкл, очень признателен. Я попробую. У вас случайно есть ссылка на учебное пособие, в котором более подробно объясняются составные элементы управления и шаблоны? - person Jacques; 05.04.2012
comment
Я не знаю ни одной статьи, которая пришла бы мне в голову. Если у вас есть еще вопросы, не стесняйтесь спрашивать. :-) - person Michael Liu; 05.04.2012

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

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

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

person cyberspy    schedule 13.08.2012