简体   繁体   English

由 CompositeControl 模板化服务器控件呈现的控件 HTML

[英]Control HTML rendered by CompositeControl Templated Server Controls

I'm building my first custom server control which inherits from CompositeControl我正在构建我的第一个自定义服务器控件,它继承自 CompositeControl

The reason for the control is to be able to have a consistent content area (HTML elements) for multiple online applications that we develop.控件的原因是为了能够让我们开发的多个在线应用程序具有一致的内容区域(HTML 元素)。

So instead of having to constantly type out:因此,不必不断地输入:

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

the developer could add a server control as follows:开发人员可以按如下方式添加服务器控件:

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

I read the article at http://msdn.microsoft.com/en-us/library/ms178657.aspx and it works, but the problem is... I don't understand why.我在http://msdn.microsoft.com/en-us/library/ms178657.aspx阅读了这篇文章并且它有效,但问题是......我不明白为什么。 (Does anyone have a link to a layman's version of an article that describes how to build these kinds of server controls?) (有没有人链接到一篇描述如何构建这些类型的服务器控件的文章的外行版本?)

Main thing I notice so far is that Asp.net is rendering a bunch of SPAN elements, which of course I don't want.到目前为止我注意到的主要事情是 Asp.net 正在呈现一堆 SPAN 元素,这当然是我不想要的。

How does one control the HTML that the new CompositeControl is outputting?如何控制新 CompositeControl 输出的 HTML?

Thanks, Jacques谢谢,雅克

PS.附言。 Here's my code so far:到目前为止,这是我的代码:

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

The extra <span> elements are coming from the TemplateOwner controls because a WebControl (which TemplateOwner inherits from) renders <span> tags by default.额外的<span>元素来自TemplateOwner控件,因为WebControlTemplateOwner从中继承)默认呈现<span>标记。 You could change TemplateOwner to specify the tag to render:您可以更改TemplateOwner以指定要呈现的标签:

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

But you don't need to create your own class to use templates.但您无需创建自己的 class 即可使用模板。 For example, you can just use Panel controls:例如,您可以只使用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);
}

A simpler solution us to use the PlaceHolder control.一个更简单的解决方案是我们使用 PlaceHolder 控件。 Like CompositeControl, this is a container control.与 CompositeControl 一样,这是一个容器控件。 Unlike CompositeControl however, it doesn't render any content at all - no containing or tags.然而,与 CompositeControl 不同的是,它根本不呈现任何内容 - 不包含或标记。

It does mean that you can't refer to the entire control programatically, like you can with a CompositeControl, but depending on what you are doing, that may not be necessary.这确实意味着您不能像使用 CompositeControl 那样以编程方式引用整个控件,但根据您的操作,这可能不是必需的。

Each subcontrol will have a unique ID though, so you can refer to child controls programatically (deal with events etc)虽然每个子控件都有一个唯一的 ID,因此您可以通过编程方式引用子控件(处理事件等)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM