The majority of my ASP.NET development time is spent on web applications. Recently however, I was creating a marketing website to complement one of those applications and realised it required a slightly different approach to that which I was used to – we needed maximum changeability for as little downtime. Switching off the option to compile the pages into the dlls was the first step but I wanted pages with as little structural code in them as possible, as they may be edited by a non-developer. I discovered that the use of template user controls was the answer to this and meant that the pages would contain controls similar to this:
1 2 3 4 | <uc:contentarea id="mycontent" runat="server"> <headingcontent>Some Heading</headingcontent> <maincontent>Lorem ipsum..</maincontent> </uc:contentarea> |
In this way, any html code that affects the layout would be hidden away and anyone changing them cannot accidently break the layout. How does one do this? It is fairly straight forward. First you create a new user control and write the html as you want it, with the areas where the content is to be inserted marked to run at server:
1 2 3 4 | <div id="mycontentcontrol"> <h1 id="heading" runat="server"></h1> <p id="content" runat="server"></p> </div> |
The differences to a standard user control occur in the codebehind:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | Imports System.ComponentModel Partial Public Class MyControl Inherits System.Web.UI.UserControl Private _headingTemplate As ITemplate = Nothing Private _contentTemplate As ITemplate = Nothing Private Sub Page_Init(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Init If Not (HeadingContent Is Nothing) Then Dim container As New ContentContainer() HeadingContent.InstantiateIn(container) heading.Controls.Add(container) heading.DataBind() End If If Not (MainContent Is Nothing) Then Dim container As New ContentContainer() MainContent.InstantiateIn(container) content.Controls.Add(container) content.DataBind() End If End Sub <TemplateContainer(GetType(ContentContainer)), _ PersistenceMode(PersistenceMode.InnerProperty), _ TemplateInstance(TemplateInstance.Single), _ Browsable(False)> _ Public Property HeadingContent() As ITemplate Get Return _headingTemplate End Get Set(ByVal value As ITemplate) _headingTemplate = value End Set End Property <TemplateContainer(GetType(ColumnContainer)), _ PersistenceMode(PersistenceMode.InnerProperty), _ TemplateInstance(TemplateInstance.Single), _ Browsable(False)> _ Public Property MainContent() As ITemplate Get Return _contentTemplate End Get Set(ByVal value As ITemplate) _contentTemplate = value End Set End Property Public Class ContentContainer Inherits Control Implements INamingContainer Friend Sub New() End Sub End Class End Class |
There is quite a lot here but it is fairly straight forward. The key to it is using the ITemplate interface for the properties that represent each of the areas you want as editable. This allows you to place the tags within the control in your page. At runtime , the content of these is placed into a control – the ContentContainer class, using the InstantiateIn method and that control is then placed into the html.