创建ListView时,控件上有一个属性,允许您在LayoutTemplate中指定PlaceHolder的ID,用于保存每个项目的控件。
<asp:ListView ID="lvTest" runat="server" ItemPlaceholderID="testPlaceholder">
<LayoutTemplate>
<ul>
<asp:PlaceHolder ID="testPlaceholder" runat="server" />
</ul>
</LayoutTemplate>
<ItemTemplate>
<li>Item</li>
</ItemTemplate>
</asp:ListView>
我正在尝试创建一个自定义的模板化服务器控件,但希望在模板本身上有一个属性,因为我希望有几个不同的模板。我非常简单,琐碎的例子如下:
using System;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace ControlLibrary
{
[ParseChildren(true)]
public class TestContainer : Control, INamingContainer
{
[PersistenceMode(PersistenceMode.InnerProperty)]
[TemplateContainer(typeof(TestContainer))]
public TestTemplate TestTemplate { get; set; }
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
DataBind();
}
public override void DataBind()
{
base.DataBind();
CreateChildControls();
}
protected override void CreateChildControls()
{
Controls.Clear();
var phTest = new PlaceHolder();
phTest.ID = "phTest";
Controls.Add(phTest);
if (this.TestTemplate != null)
this.TestTemplate.InstantiateIn(phTest);
this.ChildControlsCreated = true;
}
}
public class TestTemplate : ITemplate
{
public string Name { get; set; }
public void InstantiateIn(Control container)
{
container.Controls.Add(new LiteralControl(this.Name));
}
}
}
但是,如果我将模板添加到我的.aspx文件中,如下所示,我收到一条错误消息 CS0029:无法隐式转换类型&#39; System.Web.UI.CompiledTemplateBuilder&#39;到&#39; ControlLibrary.TestTemplate&#39;
<CustomControls:TestContainer ID="testContainer" runat="server">
<TestTemplate>
test
</TestTemplate>
</CustomControls:TestContainer>
是否可以这样做或者我必须将所有可配置属性放在父容器本身上?
感谢您提供的任何帮助!
答案 0 :(得分:2)
除模板属性声明外,您已正确完成所有操作。任何模板都必须声明为System.Web.UI.ITemplate
。只需将模板声明替换为:
public ITemplate TestTemplate { get; set; }
它应该开始工作了。有关参考,请参阅How to: Create Templated ASP.NET User Controls。
要使用模板的自定义属性进行操作,您需要再添加一个继承自集合的类:
public class TestTemplateList : List<TestTemplate> { }
并将控件的声明更改为:
[ParseChildren(true, DefaultProperty = "TestTemplates")]
public class TestContainer : Control, INamingContainer
{
[PersistenceMode(PersistenceMode.InnerProperty)]
public TestTemplateList TestTemplates { get; set; }
// ... OnLoad and DataBind left intact
protected override void CreateChildControls()
{
Controls.Clear();
var phTest = new PlaceHolder();
phTest.ID = "phTest";
Controls.Add(phTest);
if (this.TestTemplates != null)
{
foreach (var testTemplate in TestTemplates)
{
((ITemplate)testTemplate).InstantiateIn(phTest);
}
}
this.ChildControlsCreated = true;
}
}
之后你应该能够以两种方式宣布控制。您可以跳过指定TestTemplates
,因为它在DefaulProperty
中被声明为ParseChildrenAttribute
:
<CustomControls:TestContainer runat="server" ID="testContainer">
<CustomControls:TestTemplate Name="test">
</CustomControls:TestTemplate>
</CustomControls:TestContainer>
<%-- OR --%>
<CustomControls:TestContainer runat="server" ID="wc11">
<TestTemplates>
<CustomControls:TestTemplate Name="test">
</CustomControls:TestTemplate>
</TestTemplates>
</CustomControls:TestContainer>