Building a custom control with nested templates

M

Michael Vanhoutte

Hi,

I'm trying to create a templated custom asp.net server control with nested
templates and I'm having some problems in getting the nesting to work.

This is an excerpt of an aspx-file that shows what I want to do:
<form id="Form1" method="post" runat="server">
<cc1:TestControl id="TestControl1" runat="server">
<ThumbnailTemplates>
<HeaderTemplate>
<b>My Thumbnail Header</b>
</HeaderTemplate>
<FooterTemplate>
<b>My Thumbnail Footer</b>
</FooterTemplate>
</ThumbnailTemplates>
<PreviewTemplates>
<HeaderTemplate>
<b>My Preview Header</b>
</HeaderTemplate>
</PreviewTemplates>
</cc1:TestControl>
</form>

My control is supposed to display an html-page containing either thumbnails
or
previews. The user will be able to switch between the two views using a
button displayed by my control.

Regardless of which one is displayed, both interfaces have the need for a
Header, a Footer and some other stuff. Since the logic and the templates
needed for both the
thumbnails and the previews are the same, I created one container (called
TestTemplatesContainer in my code below) that contains a HeaderTemplate and a
FooterTemplate-property. I was hoping to use this container inside a
<PreviewTemplates>- and <ThumbnailTemplates>-element.

So if a user chooses thumbnail-view, I would build an interface using the
templates
of the <ThumbnailTemplates>-element; if a user chooses preview-view, I would
build an interface using the templates in <PreviewTemplates>. I want to use
two different elements for this because the HTML-code that a user of my
control would specify in the aspx-file can be very different for both views.

My problem is that I now have two nested templates that I need to deal with
in my
CreateChildControls-method, but I'm not able to get the second level to
work. I would appreciate if somebody could have a look at my code below and
tell me what I'm doing wrong. I threw away most of the code and
exception-handling so that you only have relevant code.

I really would like to do it like this (as opposed to creating sub-controls)
because
my TestControl-object is the only one that can render my complete page; these
sub-controls wouldn't be able to do it.

using System;
using System.Drawing;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.ComponentModel;

namespace MyControl
{
/// <summary>
/// TestControl is my actual control.
/// </summary>
[
ToolboxData("<{0}:TestControl runat=server></{0}:TestControl>"),
ParseChildren(ChildrenAsProperties=true)
]
public class TestControl: System.Web.UI.WebControls.WebControl,

System.Web.UI.INamingContainer
{
private TestTemplatesContainer m_objThumbnailTemplatesContainer = null;
private ITemplate m_objThumbnailTemplates = null;

[
TemplateContainer(typeof(TestTemplatesContainer)),
PersistenceMode(PersistenceMode.InnerProperty),
BrowsableAttribute(false)
]
public ITemplate ThumbnailTemplates
{
get
{
return m_objThumbnailTemplates;
}
set
{
m_objThumbnailTemplates = value;
}
}

protected override void CreateChildControls()
{
m_objThumbnailTemplatesContainer = new TestTemplatesContainer();
m_objThumbnailTemplates.InstantiateIn(m_objThumbnailTemplatesContainer);

// I was hoping that m_objThumbnailTemplatesContainer.HeaderTemplate
in the
// following test would not have been null. Unfortunately, it always is.
// What is wrong here?
if (!Object.Equals(m_objThumbnailTemplatesContainer.HeaderTemplate,
null))
{
TestHeaderTemplateContainer objContainer = new
TestHeaderTemplateContainer();

m_objThumbnailTemplatesContainer.HeaderTemplate.InstantiateIn(objContainer);

Controls.Add(new LiteralControl("<B>start"));
Controls.Add(objContainer);
Controls.Add(new LiteralControl("end</B>"));
}
else
{
Controls.Add(new LiteralControl("should never display."));
}

}
}

/// <summary>
/// TestHeaderTemplateContainer is the container used for
/// <HeaderTemplate>
/// </summary>
[
ToolboxItem(false)
]
public class TestHeaderTemplateContainer: System.Web.UI.Control,

System.Web.UI.INamingContainer
{
}

/// <summary>
/// TestTemplatesContainer is the container used for
/// <ThumbnailTemplates> and <PreviewTemplates>.
/// </summary>
[
ToolboxItem(false),
ParseChildren(ChildrenAsProperties=true)
]
public class TestTemplatesContainer: System.Web.UI.Control,

System.Web.UI.INamingContainer
{
private ITemplate m_objHeaderTemplate = null;

[
TemplateContainer(typeof(TestHeaderTemplateContainer)),
PersistenceMode(PersistenceMode.InnerProperty),
BrowsableAttribute(false)
]
public ITemplate HeaderTemplate
{
get
{
return m_objHeaderTemplate;
}
set
{
m_objHeaderTemplate = value;
}
}
}
}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,763
Messages
2,569,563
Members
45,039
Latest member
CasimiraVa

Latest Threads

Top