我正在构建我的第一个继承自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元素,这当然是我不想要的。
如何控制新CompositeControl输出的HTML?
谢谢, 雅克
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
{
}
}
答案 0 :(得分:1)
额外的<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);
}
答案 1 :(得分:0)
使用PlaceHolder控件的一个更简单的解决方案。 像CompositeControl一样,这是一个容器控件。 然而,与CompositeControl不同,它根本不呈现任何内容 - 不包含或标记。
这确实意味着您无法以编程方式引用整个控件,就像使用CompositeControl一样,但根据您的操作,可能没有必要。
每个子控件都有一个唯一的ID,所以你可以编程方式引用子控件(处理事件等)