我有一个正在加载模板区域内容的ascx用户控件。例如:
<。>在.ascx文件中:<%@ Control Language="C#" CodeBehind=....." %>
[some html ....]
<asp:PlaceHolder runat="server" ID="ctlContentHolder" />
[some other html ...]
然后在后面的代码中:
[Browsable (false)]
[PersistenceMode (PersistenceMode.InnerProperty)]
public ITemplate ContentTemplate
{
get; set;
}
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
ContentTemplate.InstantiateIn (ctlContenuHolder);
}
我可以像这样使用控件:
<xxx:myControl runat="server" id="myCoolControl">
<ContentTemplate>
The content of my cool control here.
</ContentTemplate>
</xxx:myControl>
我想做的是,内容模板数量不确定,类似于转发器,但每个模板中的内容不同。我可以用这样的东西:
<xxx:myControl runat="server" id="myCoolControl">
<ContentTemplate>
Some content here
</ContentTemplate>
<ContentTemplate>
Some completely different content here
</ContentTemplate>
</xxx:myControl>
有人知道如何实现这样的控制吗?
答案 0 :(得分:0)
这可能。这是一些代码,YMMV。我不在乎解释它ATM。它是initially based this question,但最终我有了这种方法,因为那时我没有得到真正的 ITemplate对象,而是带有ITemplate接口的存根对象..或者,大多数都没用。
请注意,每个Control只有一个模板,但它自己的集合有许多这样的控件。它有点冗长,但我找不到轻松删除其他级别的方法。
使用示例:
<seis:SmartTemplate runat="server">
<NamedTemplates>
<seis:NamedTemplate Name="Name1" runat="server">
<Content>
Template1
</Content>
</seis:NamedTemplate>
<seis:NamedTemplate Name="Name2" runat="server">
<Content>
Template2
</Content>
</seis:NamedTemplate>
...
代码:
using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Web.UI;
namespace Channelmatter.SBCJC.SEI.UISupport
{
/// <summary>
/// Provides the ability to create templates in Markup that
/// can be applied dynamically.
/// </summary>
[ToolboxData("<{0}:SmartTemplate runat='server'></{0}>")]
[ParseChildren(true)]
[PersistChildren(false)]
public class SmartTemplate : Control, ITemplate
{
public SmartTemplate()
{
NamedTemplates = new NamedTemplateCollection();
}
public class SelectTemplateEventArgs : EventArgs
{
// The control that the template instantiates into
public Control Container { get; set; }
public object DataItem { get; set; }
// If set to a non-null value, represents the template name to use
public string TemplateName { get; set; }
}
public delegate void SelectTemplateEventHandler(object sender, SelectTemplateEventArgs args);
/// <summary>
/// Allow the template to be selected based upon the Container and DataItem.
/// The event should specify the TemplateName to use.
/// </summary>
[Browsable(true)]
public event SelectTemplateEventHandler SelectTemplate;
[PersistenceMode(PersistenceMode.InnerProperty)]
public NamedTemplateCollection NamedTemplates { get; set; }
/// <summary>
/// Find a template with the given name.
/// Returns null if there is no such template.
/// </summary>
public ITemplate FindTemplate(string name)
{
foreach (var namedTemplate in NamedTemplates)
{
if (namedTemplate.Name == name)
{
return namedTemplate;
}
}
return null;
}
public void InstantiateIn(Control container)
{
var dataContainer = (IDataItemContainer)container;
var dataItem = dataContainer.DataItem;
if (SelectTemplate != null)
{
var args = new SelectTemplateEventArgs
{
Container = container,
DataItem = dataItem,
};
SelectTemplate(this, args);
var namedTemplate = FindTemplate(args.TemplateName);
if (namedTemplate != null)
{
namedTemplate.InstantiateIn(container);
}
}
}
}
[ToolboxData("<{0}:NamedTemplate runat='server'></{0}>")]
[ParseChildren(true)]
[PersistChildren(false)]
public class NamedTemplate : Control, INamingContainer, ITemplate
{
public class BeforeInstantiateInEventArgs : EventArgs
{
public Control Container;
public object DataItem;
/// <summary>
/// If set to a non-null value this will be used instead of DataItem.
/// </summary>
public object MappedDataItem;
}
public delegate void BeforeInstantiateInEventHandler(object sender, BeforeInstantiateInEventArgs args);
/// <summary>
/// Can be used to do programatic things before the template is initiated.
/// </summary>
[Browsable(true)]
public event BeforeInstantiateInEventHandler BeforeInstantiateIn;
[Browsable(true)]
public string Name { get; set; }
[Browsable(false)]
[TemplateContainer(typeof (NamedTemplateContainer), BindingDirection.TwoWay)]
[TemplateInstance(TemplateInstance.Multiple)]
[PersistenceMode(PersistenceMode.InnerProperty)]
public ITemplate Content { get; set; }
public void InstantiateIn(Control container)
{
var dataContainer = (IDataItemContainer)container;
var dataItem = dataContainer.DataItem;
if (BeforeInstantiateIn != null)
{
var args = new BeforeInstantiateInEventArgs
{
Container = container,
DataItem = dataItem,
};
BeforeInstantiateIn(this, args);
if (args.MappedDataItem != null)
{
dataItem = args.MappedDataItem;
}
}
var namedTemplateControl = new NamedTemplateContainer(dataItem);
Content.InstantiateIn(namedTemplateControl);
container.Controls.Add(namedTemplateControl);
}
}
public class NamedTemplateCollection : Collection<NamedTemplate>
{
}
public class NamedTemplateContainer: Control, IDataItemContainer
{
readonly private object dataItem;
public NamedTemplateContainer(object dataItem)
{
this.dataItem = dataItem;
}
public object DataItem
{
get { return dataItem; }
}
public int DataItemIndex
{
get { throw new NotImplementedException(); }
}
public int DisplayIndex
{
get { throw new NotImplementedException(); }
}
}
}