Follow Our FB Page << >> for Daily Laughter. We Post Funny, Viral, Comedy Videos, Memes, Vines...

when u r designing where how do u design other than drag
and drop method in the project of

Answer Posted / chauhan rakesh botad

Web developers moving to ASP.NET face the problem of
creating a Web page template to enforce a consistent look
and feel across a Web site. When your organization or
customer wants to tweak the appearance of a site, you don't
want to go through large numbers of Web pages to make
identical changes. You want to change a single template used
by all of your Web pages.

With the inheritance capability built into the .NET
languages, you have several choices available to you for
creating such a template. At the end of this article, you'll
find links to other articles that explain different Web
template approaches. Each approach has its advantages and
disadvantages, and you'll want to know the options available
to you and your team. Compare them all and select the
approach that makes sense for your Web application.

The advantage of the technique I present in this article is
its simplicity. You create your visual Web page template as
a single ASPX in the Visual Studio .NET designer. Then you
route each incoming page request for handling by the
template, which displays the content of the specific page

Except for the source of the content, the visual Web page
template described in this article resembles the templates
used for database-driven Web sites. This technique avoids
the need to hard-code lots of HTML. (Check out the amount of
hard-coded HTML required by other popular approaches.)

The VbTemplate demonstration project (view demo in new
browser window) illustrates the technique that I explain in
this article. Take a look at the different pages in the
demo, and then keep the demonstration window open to
experiment with while you read the explanation of how this
template works. For this demonstration I used Visual Basic
.NET, but you can use the .NET language of your choice.
Designing the Template

All five pages in the VbTemplate demonstration share a
single ASPX file, index.aspx. The design of index.aspx (see
Figure 1) controls the appearance of all pages.

Figure 1. The index.aspx file is the only ASPX file in the
VbTemplate demonstration project.
Creating a Web Page Template, Figure 1.

By using Visual Studio .NET, you gain the ability to drag
and drop controls on the designer and you get a visual
impression of how the pages in the Web site will look. For
this demo, I dropped the default Styles.css file on the
designer to give the template some style, then added CSS
styles—only three, as it turned out—when I needed them.

You can see the CSS styles I added (see Listing 1) in the
Visual Studio screenshot in Figure 1. The Selected style
applies to the bold font labels in the Pages cell. When a
page is rendered, a bold font label names the page to be
displayed in the browser, and all of the other pages show up
as links. As I'll demonstrate shortly, the code behind
index.aspx determines which alternative in the page list is
visible, depending upon which page the visitor has requested.

Listing 1. CSS classes added to Styles.css for the
VbTemplate demo.

font-weight: bold;
color: #003366;

color: #003366;

font-size: .7em;
color: #003366;
text-align: center;

The Time style applies only to the lblTime label control in
the top cell of the template. I added the time stamp to
demonstrate that output caching works correctly using this
visual Web page template technique. The Copyright style
applies to copyright notice on the bottom line in Figure 1.

Because index.aspx acts as a template for all of the Web
pages in the site, its content cannot be determined until
the visitor selects a particular page. Therefore I added the
PlaceHolder control plcContent to hold the actual content
once known. In the VbTemplate demo, the content for each
page resides in a separate ASCX user control file. (At the
end of this article, I discuss a variant of this technique
that does not use ASCX files for content.)
Looking at the Template Structure

As the only ASPX file in the VbTemplate demo, index.aspx
naturally receives the startup page designation. You can see
at the top of Listing 2, however, that the Page directive
specifies VbTemplate.PageBase as the base class for the page
instead of Visual Studio's default value of
VbTemplate.index. I reserved the latter class name for the
user control that contains the content for index.aspx.

Listing 2. The HTML listing for index.aspx.

<%@ Page Language="vb" AutoEventWireup="false"
Inherits="VbTemplate.PageBase" %>
<%@ OutputCache Duration="1000" Location="Server"
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<asp:literal id="litTitle"
<meta name="description" content="Visual Web Template Demo">
<meta name="keywords" content="ASP.NET, VB.NET, Visual,
<meta http-equiv="Content-Type" content="text/html;
<meta content="Microsoft Visual Studio.NET 7.0"
<meta content="Visual Basic 7.0" name="CODE_LANGUAGE">
<meta content="JavaScript" name="vs_defaultClientScript">
<link href="Styles.css" type="text/css" rel="stylesheet">
<form id="Form1" method="post" runat="server">
<table id="tblMain" cellspacing="1" cellpadding="1"
width="100%" border="0">
<td align="middle" colspan="2">
<h1>Visual Web Page Template</h1>
<p><asp:label id="lblTime" runat="server"
11:35:10 AM</asp:label></p>
<hr width="100%">
<td valign="top" width="25%">
<asp:label id="lbl_index" runat="server"
visible="False" cssclass="Selected">Home
<asp:hyperlink id="lnk_index" runat="server"
<asp:label id="lbl_static_text" runat="server"
visible="False" cssclass="Selected">Static Text
<asp:hyperlink id="lnk_static_text" runat="server"
navigateurl="static_text.aspx">Static Text
<asp:label id="lbl_dynamic_text" runat="server"
visible="False" cssclass="Selected">Dynamic Text
<asp:hyperlink id="lnk_dynamic_text" runat="server"
navigateurl="dynamic_text.aspx">Dynamic Text
<asp:label id="lbl_button_click" runat="server"
visible="False" cssclass="Selected">Button Click
<asp:hyperlink id="lnk_button_click" runat="server"
navigateurl="button_click.aspx">Button Click
<asp:label id="lbl_text_input" runat="server"
visible="False" cssclass="Selected">Text Input
<asp:hyperlink id="lnk_text_input" runat="server"
navigateurl="text_input.aspx">Text Input
<td valign="top" width="75%">
<asp:placeholder id="plcContent" runat="server">
<td align="middle" colspan="2">
<hr width="100%">
<div class="Copyright">
<asp:label id="lblYears" runat="server">© 2001
- 2002
&nbsp;SoftMedia Artisans, Inc. All Rights

The OutputCache directive in Listing 2 specifies server
caching as the default condition for all pages generated by
this template. If you check the time stamp on the Home page,
then return to the Home page after viewing other pages,
you'll see that you receive a cached version of the Home
page on your second request. In a later example, I show how
to turn off output caching for individual pages where it is
not appropriate.

Depending upon your application's requirements, you might
need a more sophisticated OutputCache directive or you might
need to create user controls for finer control over caching.
(In Chapter 10 of our book Programming the Web with Visual
Basic .NET, we explain, with code examples, the output
caching options available.)

Designers commonly use HTML tables to provide a liquid
design structure for their Web pages. When you resize the
browser window, the text flows within the table to
accomodate its new size. As you can see in Listing 2, I've
adopted that strategy for this demo.

In the head section of the HTML, the title element contains
the following line:

<asp:literal id="litTitle" runat="server">Template</asp:literal>

Because the title will change depending upon the page
actually requested, I inserted a Literal control to receive
the appropriate title programmatically.

In the Pages cell, all of the links start with Visible=True
(the default) and all of the corresponding Selected labels
start with Visible=False. Once the page requested is known,
the template code reverses the values of the Visible
properties corresponding to that page. Of course the code
cannot do that unless it knows what page the visitor
requested. Let's take a look at how that's done.
Routing an Incoming Request to the Template

The Global.asax.vb file contains handlers for events that
fire before and after page processing. The event to use for
routing an incoming request to the template is
Application.BeginRequest. Listing 3 contains the code that
does this routing in the VbTemplate demo.

Listing 3. The handler for the Application.BeginRequest
event in the global.asax.vb file.

Sub Application_BeginRequest( _
ByVal sender As Object, ByVal e As EventArgs)

' Fires at the beginning of each request
Dim sPath As String = Request.Path.ToLower
Dim iStart As Integer = sPath.LastIndexOf("/") + 1
Dim sPage As String = sPath.Substring( _
iStart, sPath.IndexOf(".aspx") - iStart)
If Not sPage = "index" Then
Context.RewritePath(sPath.Substring(0, iStart) _
& "index.aspx?page=" & sPage)
End If
End Sub

The code in Listing 3 extracts the name of the page
requested from the Request.Path property. If it is not the
index page, the code uses the Context.RewritePath method to
route the request to the template, appending a query string
with the name of the page actually requested. If the request
is for the index page, the code does not reroute it.

Note that on a postback, the Request.Path will request the
index page and will be accompanied by a query string
identifying the page originally requested. In the next
section we look at how the template code uses the query
string, however it originated, to determine the content of
the response.
Handling the Incoming Request

As I mentioned earlier, the code behind the template bears
the class name PageBase even though it resides in the
index.aspx.vb file. The template code for this demo, shown
in Listing 4, does its work in the handlers for the
Page.Load and Page.PreRender events.

Listing 4. The PageBase code in index.aspx.vb.

Option Strict On
Imports System.Web.UI.WebControls

Public Class PageBase
Inherits System.Web.UI.Page
Protected WithEvents litTitle As Literal
Protected WithEvents lblTime As Label
Protected WithEvents lbl_index As Label
Protected WithEvents lnk_index As HyperLink
Protected WithEvents lbl_static_text As Label
Protected WithEvents lnk_static_text As HyperLink
Protected WithEvents lbl_dynamic_text As Label
Protected WithEvents lnk_dynamic_text As HyperLink
Protected WithEvents lbl_button_click As Label
Protected WithEvents lnk_button_click As HyperLink
Protected WithEvents lbl_text_input As Label
Protected WithEvents lnk_text_input As HyperLink
Protected WithEvents lblYears As Label
Protected WithEvents plcContent As PlaceHolder

#Region " Web Form Designer Generated Code "
'This call is required by the Web Form Designer.
<System.Diagnostics.DebuggerStepThrough()> _
Private Sub InitializeComponent()

End Sub

Private Sub Page_Init(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Init
'CODEGEN: This method call is required
' by the Web Form Designer
'Do not modify it using the code editor.
End Sub
#End Region

Private _sPage As String
Private _oContent As ControlBase

Private Sub Page_Load(ByVal sender As System.Object, _
ByVal e As System.EventArgs) _
Handles MyBase.Load

'Determine the page requested
_sPage = Request.QueryString("page")
If _sPage Is Nothing Then _sPage = "index"

'Use time stamp to show caching
Me.lblTime.Text = Now.ToLongTimeString

'Set copyright years
Me.lblYears.Text = "© 2001 - " & Year(Today).ToString

'Add content from user control
_oContent = CType( _
Page.LoadControl(_sPage & ".ascx"), ControlBase)

'Show the page selected in bold text
'Unsupported page request
Me.plcContent.Controls.Add(New LiteralControl( _
"Please select a link from the list."))
End Try
End Sub

Private Sub Page_PreRender(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles MyBase.PreRender
If (Not _oContent Is Nothing) Then
'Page request is supported
If (_oContent.Title <> String.Empty) Then
'Get page title from user control
Me.litTitle.Text = _oContent.Title
'Get page title from link text
Dim oLink As HyperLink = _
CType(Me.FindControl("lnk_" & _sPage), HyperLink)
Me.litTitle.Text = oLink.Text
End If
End If
End Sub

Private Sub ShowSelection(ByVal Page As String)
'Turn off link for the current selection
Dim oLink As HyperLink = _
CType(Me.FindControl("lnk_" & Page), HyperLink)
oLink.Visible = False
Dim oLabel As Label = _
CType(Me.FindControl("lbl_" & Page), Label)
oLabel.Visible = True
End Sub
End Class

The Page_Load code in Listing 4 retrieves the query string
passed by the Application_BeginRequest procedure like this:

_sPage = Request.QueryString("page")
If _sPage Is Nothing Then _sPage = "index"

If the visitor requests the index page directly, the query
string will be empty, so the second line is necessary.

Using this visual Web page template technique, the content
for each page resides in an ASCX (user control) file. For
example, the content for index.aspx resides in the
index.ascx file. When the ASCX corresponding to the request
exists, the following lines add the user control to the
PlaceHolder located in the Content section of the template:

_oContent = CType( _
Page.LoadControl(_sPage & ".ascx"), ControlBase)

Note that ControlBase, rather than UserControl, is the base
class for all of the ASCX files in this demo. I'll explain
why in the next section of this article.

If the ASCX does not exist, the Catch block adds a generic
message instead. (Because the Application_BeginRequest
procedure routes all incoming ASPX requests to the template,
ASP.NET cannot identify a Page Not Found error.)

That's all it takes to add the requested content to the
page. However, the display of the template itself needs to
be changed to reflect the actual page requested, like this:


The ShowSelection procedure (see the bottom of Listing 4)
replaces the link to the selected page with a bold font label.

Finally, the Page_PreRender procedure performs any tasks
required because of actions taken by the code behind the
ASCX file. For this demo, we take this opportunity to set
the page title (which displays at the top of the browser
window) to the value of the user control's Title property,
like this.

Me.litTitle.Text = _oContent.Title

If the user control doesn't supply a Title value, the
procedure simply sets the page title to the text used for
the page link.

Having looked at how the template code uses the Title
property, we're now going to examine the mechanism actually
used to supply the page title and to provide other common
functionality for the ASCX files.
Subclassing the UserControl Class

By default, the code behind a user control inherits directly
from the UserControl class. If the content portions of your
Web application contain no common processing requirements,
that default works fine.

Usually, however, you'll want to provide some common
functionality beyond that provided by the UserControl class.
To do so, you create a custom base class like that shown in
Listing 5. The ControlBase class in the demo inherits from
UserControl, but exposes two properties and adds the link to
this article that appears at the bottom of the content.

Listing 5. The ControlBase class code in ControlBase.vb.

Option Strict On
Imports System
Imports System.Web
Imports System.Web.UI

Public Class ControlBase
Inherits UserControl

Private _sTitle As String

Public Property Title() As String
Return _sTitle
End Get
Set(ByVal Value As String)
_sTitle = Value
End Set
End Property

Private _sAppend As String

Public Property Append() As String
Return _sAppend
End Get
Set(ByVal Value As String)
_sAppend = Value
End Set
End Property

Private Sub Page_PreRender(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles MyBase.PreRender
If Append <> String.Empty Then
Me.Controls.Add(New LiteralControl(Append & vbCrLf))
End If

Dim sFoot As String = _
"<hr width='100%' />" & vbCrLf _
& "<div>Read about this template: " _
& "<a href='" _
& "articles/vb_templates.aspx'>" _
& "Creating a Visual Web Page Template" _
& "</a>.</div>" & vbCrLf
Me.Controls.Add(New LiteralControl(sFoot))
End Sub
End Class

When the code behind a user control inherits from
ControlBase, it inherits all of the UserControl
functionality as well as the functionality provided in
Listing 5.

The Title property allows the user control to specify the
title to be displayed at the top of the browser window. At
the end of the last section we looked at the code that uses
this property to set the page title.

The Append property provides a means to append text or HTML
to the static content of the ASCX page. The dynamic_content
page demonstrates the use of this property.

The Page_PreRender procedure appends the text, if any, to
the Controls collection. Then it adds the link at the bottom
of the content.
Providing Static Content

Aside from the link to this article, which always appears,
two of the Web pages in this demo display static text only.
The first is the Home page, index.aspx. Figure 2 shows how
its text appears in the Visual Studio .NET designer.

Figure 2. The index.ascx file provides the content for the
index.aspx Web page.
Creating a Web Page Template, Figure 2.

When you work in the designer, you can have Visual Studio
.NET create HTML for you. The italicized text in Figure 2,
for example, was formatted by highlighting the desired text
and clicking the italics icon. You can create a link by
highlighting some text and pressing Ctrl-L, and so on.
Listing 6 provides the HTML that was created by typing the
text shown in Figure 2.

Listing 6. The HTML listing for the index.ascx user control.

<%@ Control Language="vb" AutoEventWireup="false"
Codebehind="index.ascx.vb" Inherits="VbTemplate.index"
This project uses a single ASPX template file,
<em>index.aspx</em>, to display all five of its content
The actual content for each page resides in its ASCX file.
The content for this page, for example, can be found
in <em>index.ascx</em>.
The mechanism used to forward each incoming request is the
Context.RewritePath method in the Application_BeginRequest
event handler. A query string supplies the name of the page
originally requested by the visitor.
Click the links to see how the template handles
different types of content.

The second of the text-only Web pages in this demo is
static_text. This Web page displays the content of the
static_text.ascx file. Figure 3 shows its content in the
Visual Studio .NET designer.

Figure 3. The static_text.ascx file provides the content for
the static_text.aspx Web page.
Creating a Web Page Template, Figure 3.

I don't show the code behind either index.ascx or
static_text.ascx in this article because both listings do
nothing but set the page title property in the same manner
as the listings that follow. Let's move on to the user
controls that do a bit more.
Appending Content Dynamically

The content for the dynamic_text Web page resides in the
dynamic_text.ascx file. This content includes a short
unnumbered list, as shown in Figure 4.

Figure 4. The dynamic_text.ascx file provides the content
for the dynamic_text.aspx Web page.
Creating a Web Page Template, Figure 4.

If you request the Dynamic Text page of the demo, you see an
additional paragraph appended to the text in Figure 4.
Listing 7 shows how the ControlBase.Append property was set.
Note that, as I promised, the dynamic_text class inherits
from ControlBase instead of UserControl.

Listing 7. Code in the Page_Load event handler in
dynamic_text.ascx.vb specifies content to be appended by

Option Strict On
Public MustInherit Class dynamic_text
Inherits ControlBase

#Region " Web Form Designer Generated Code "
'This call is required by the Web Form Designer.
<System.Diagnostics.DebuggerStepThrough()> _
Private Sub InitializeComponent()

End Sub

Private Sub Page_Init(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Init
'CODEGEN: This method call is required
' by the Web Form Designer
'Do not modify it using the code editor.
End Sub
#End Region

Private Sub Page_Load(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Load
Me.Title = "Visual Web Page Template Demo: Dynamic Text"
Me.Append = "<p>But this sentence was appended " _
& "programmatically during the Page.Load event " _
& "in <em>dynamic_text.ascx.vb</em>.<p>"
End Sub
End Class

You can also see in Listing 7 how the Page_Load procedure
sets the Title property. Similar statements exist in all of
the ASCX.VB code files in this demo.

To this point, none of the pages we've discussed post back
to the server. And in Web applications that supply content
to visitors, that is the normal situation. As I'm about to
show, however, this technique can also handle postbacks.
Posting Back to the Template

Using the visual Web page template technique described in
this article, postbacks are handled in the ASCX.VB code
files for their respective pages. The button_click page
illustrates the use of an HTML input button to post back to
the server. Figure 5 depicts the content for the page as it
appears in the Visual Studio .NET designer.

Figure 5. The button_click.ascx file provides the content
for the button_click.aspx Web page.
Creating a Web Page Template, Figure 5.

Working in the designer, you can double-click a button
control to direct Visual Studio .NET to stub in the proper
event handler for you. I did this with the button in Figure
5 to start the btnClick_ServerClick procedure at the bottom
of Listing 8.

Listing 8. Code in the btnClick_ServerClick event handler in
button_click.ascx.vb reports when the user control
recognizes a button click in the browser.

Option Strict On
Imports System.Web.UI.HtmlControls

Public MustInherit Class button_click
Inherits ControlBase
Protected WithEvents btnClick As HtmlInputButton
Protected WithEvents pReply As HtmlGenericControl

#Region " Web Form Designer Generated Code "
'This call is required by the Web Form Designer.
<System.Diagnostics.DebuggerStepThrough()> _
Private Sub InitializeComponent()

End Sub

Private Sub Page_Init(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Init
'CODEGEN: This method call is required
' by the Web Form Designer
'Do not modify it using the code editor.
End Sub
#End Region

Private Sub Page_Load(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Load
Me.Title = "Visual Web Page Template Demo: Button Click"
End Sub

Private Sub btnClick_ServerClick( _
ByVal sender As System.Object, _
ByVal e As System.EventArgs) _
Handles btnClick.ServerClick
pReply.InnerText = "You clicked the button!"
End Sub
End Class

If you request the Button Click page of the demo, you can
verify that the event handler in Listing 8 gets control.
Click the button and note the response.

Now take a look at the URL displayed in the address box of
your browser. The postback returns the URL built in the
Application_BeginRequest procedure when it routed the
original request to the template.

If your Web application requires postbacks and you want to
conceal the postback URL from your visitors, you can do so.
The next example shows how.
Accepting Input from the Visitor

The text_input.aspx page provides an HTML input text box for
entering text plus an HTML input submit button for posting
the text back to the server. Figure 6 shows the appearance
of the text_input content in Visual Studio .NET.

Figure 6. The text_input.ascx file provides the content for
the text_input.aspx Web page.
Creating a Web Page Template, Figure 6.

If you request the Text Input page of the demo, you can test
its operation for yourself. The server returns the text you
enter while retaining the original URL. In the code behind
the text_input.ascx file, shown in Listing 9, the Page_Load
and btnSubmit_ServerClick procedures work together to
accomplish this result.

Listing 9. The event handlers in text_input.ascx.vb return
data entered at the browser while concealing the URL of the

Option Strict On
Imports System.Web.UI.HtmlControls

Public MustInherit Class text_input
Inherits ControlBase
Protected WithEvents txtInput As HtmlInputText
Protected WithEvents btnSubmit As HtmlInputButton
Protected WithEvents pReply As HtmlGenericControl

#Region " Web Form Designer Generated Code "
'This call is required by the Web Form Designer.
<System.Diagnostics.DebuggerStepThrough()> _
Private Sub InitializeComponent()

End Sub

Private Sub Page_Init(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Init
'CODEGEN: This method call is required
' by the Web Form Designer
'Do not modify it using the code editor.
End Sub
#End Region

Private Const sPage As String = "text_input"

Private Sub Page_Load(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Load
Me.Title = "Visual Web Page Template Demo: Text Input"
Dim sInput As String = CStr(Session(sPage))
If Not sInput = String.Empty Then
txtInput.Value = sInput
pReply.InnerText = "You submitted: " & sInput
Session(sPage) = Nothing
End If
End Sub

Private Sub btnSubmit_ServerClick( _
ByVal sender As System.Object, _
ByVal e As System.EventArgs) _
Handles btnSubmit.ServerClick
Session(sPage) = txtInput.Value
Response.Redirect(sPage & ".aspx")
End Sub
End Class

Here is the example I promised where output caching should
be turned off. If you plan to return data to the visitor in
the same Web page that captured the data, output caching
will defeat your purpose: ASP.NET will return the original
page from the cache without ever executing your code. In
Listing 9, the Page_Load procedure kills output caching (for
the text_input page only) like this:


Check the time stamps on the demo pages to verify that
output caching does not apply to the text_input page.

The text_input page conceals the template URL after postback
by means of these two statements in the
btnSubmit_ServerClick procedure:

Session(sPage) = txtInput.Value
Response.Redirect(sPage & ".aspx")

The code saves the value entered by the visitor in a session
state variable, then uses the Response.Redirect method to
request a fresh copy of the Web page. When issuing the
response to this request, the Page_Load procedure retrieves
the value from session state and returns it to the visitor.

I've taken you through this demo to illustrate the basic
concepts of this simple visual Web page template technique.
You can, of course, add many bells and whistles to the basic
structure if your Web application needs them.

But there are many ways to skin a cat. To conclude this
article, I'm going to provide some information about
alternative approaches that you might take.
Selecting a Template Approach

If the content for your Web site resides in a database, you
can use a visual Web page template technique identical to
the one described in this article, except that the content
comes from the database instead of from ASCX files. Here
too, a single ASPX file serves up many different Web pages.

In Chapter 15 of our book Programming the Web with Visual
Basic .NET, we provide a complete case study that contains
two visual Web page templates of this type. One template
provides database content selected by the visitor via either
a search or a browse. The other template provides browse
listings by category. Our sample chapter contains the
Application_BeginRequest procedure needed to distinguish
between the templates, plus other code required for the
database approach.

The visual Web page template technique explained in this
article works well for many Web sites, particularly
content-centric sites. However, there is no "one size fits
all" in Web programming. I recommend that you look at and
evaluate the approaches described by other authors too
before you settle upon an approach for your project.

Jonathan Goodyear wrote offsite link.Create Page Templates
and, later, offsite link.Page Templates Revisited in Visual
Studio Magazine. Philip Quinn wrote offsite link.Page
Templates, available at Peter Provost wrote
offsite link.ASP.NET Page Templates, available at The Code
Project. All of these authors describe ways to use
inheritance to build a Web site with a consistent look and
feel. Paul Wilson maintains a offsite link.Web site that
uses inheritance throughout, with source code available for
download. By reading the information at these links, you can
determine how other Web page template approaches compare
with the technique described in this article.

Only you can determine the best approach for your project.
Factors to consider include the development time available,
the programming skills of your team, and the unique
requirements of your Web application. Whichever approach you
choose, creating a Web page template will improve both the
consistency and maintainability of your Web site.
Downloading the Source Code

To try out the demo I used in this article, and to
experiment with it yourself, download the source code and
give it a test drive. Here's how to install it:

In Visual Studio .NET, create a Visual Basic ASP.NET Web
Application named VbTemplate.
Unzip the files in and copy them to
Inetpub\wwwroot\VbTemplate (overwrite existing files).
In the Visual Studio Solution Explorer, click the "Show
All Files" icon.
Select the new ASPX, ASCX, and VB files, right click,
then choose "Include In Project".
Toggle off the "Show All Files" options (unless you
prefer otherwise).
Right click index.aspx and select "Set As Start Page".
Delete WebForm1.aspx.

.NET Shape Library: A Sample Designer

Get the samples for this article. Unzip the folder and
double-click either the VB or C# VS.NET solution.

The Shape Library provides a comprehensive example of
writing a designer in the .NET Framework. It starts with a
very simple set of runtime vector drawing components: the
shape library, and adds design-time support for these
components. The design-time code provides many examples of
the rich features available to .NET Framework designers.
Compiling and running the sample

The sample is written as a Visual Studio solution containing
two C# projects. One project is the ShapeLibrary itself and
the other is a sample project to test the library. Load up
the solution and build it. Once it is built you can
experiment with the test project. Open MyShape.cs to
manipulate the shape designer. To add additional shapes, you
must first add the shape components to the toolbox. To do
this, right click on the toolbox and choose Customize. Then
click on the .NET Framework Components tab and click the
Browse button. Navigate to the bin\debug directory of the
ShapeLibrary project and choose ShapeLibrary.dll. This will
select the components in the dialog; just click on the check
box to check them all and they will appear on the current
tab of the toolbox. Now you can put them on the shape
designer's design surface.

To view your shape's changes on a form, you can open the
TestForm.cs file. This file has an instance of your shape on
it. If you have made changes to the shape, rebuilding your
test project will update the form. Pressing F5 will execute
the sample form, showing your shape.
Runtime components

The shape library's runtime components consist of six total

Shape is the base class for all shapes. Shape is abstract
and doesn't define any properties because shapes can have
various characteristics. For example, Shape does not provide
any sort of bounding box because for some shapes, like
lines, this property does not make sense. All shapes can be
drawn onto a graphics object, however, so Shape provides a
single abstract method named Draw. Shape derives from
System.ComponentModel.Component. The reason for this will be
covered in a later section.

The Line class is derived from Shape. It implements the Draw
method to draw a line. It also adds several properties to
Shape that help to define the line. The StartPoint and
EndPoint properties describe the starting and ending points
of the line, and the Color property determines what color
the line will be.

The Ellipse class is derived from Shape. It implements the
Draw method to draw an ellipse. The Ellipse object also
defines its own properties that are used to define the
characteristics of the ellipse. Ellipse offers a Bounds
property which describes the bounding rectangle for the
ellipse, a Color property which defines the color of the
line used to draw the ellipse, and a Fill property. The Fill
property uses a custom data type called ShapeFill, which
provides a few ways that the ellipse's interior can be filled.

The ShapeContainer class is also derived from Shape.
ShapeContainer does no drawing of its own, but it provides a
collection of shapes. When ShapeContainer is asked to draw,
it iterates through its collection of shapes, asking each
shape to draw.

The ShapeFill object derives from object and provides a few
ways to fill objects. ShapeFill contains a Brush object that
is used to fill areas with a pattern or color, and also
provides a few static pre-built instances of itself so
developers can pick a ShapeFill at design time from a
drop-down list.

Shapes have been designed only to use classes from
System.Drawing. This allows a shape object to be used on
both Windows Forms applications and ASP.Net applications. A
common use will be to have a shape draw itself on a Windows
Forms control. This requires a small amount of "glue" code
to connect a control's paint event to the shape's Draw
method. Instead of requiring the user to write this code, we
provide a special adapter object. The adapter has a method
called Connect that accepts a control and a shape. The
adapter then connects the control's paint event to the
shape's draw method. This generally wouldn't be much of a
help to the user, but in our case we have also provided some
additional design-time code to automatically create adapters
when shapes are placed on Windows Forms objects.
The Base Class: Component vs. Object

Why does Shape derive from System.ComponentModel.Componet
while ShapeFill and WindowsFormsAdapter do not? This is a
requirement of the .NET Framework designer architecture. The
designer architecture works with any type of object, but
designers (described later) can only be attached to objects
that implement System.ComponentModel.IComponent. Objects
that implement IComponent can also be added to a container
object that implements System.ComponentModel.IContainer.
This container is responsible for controlling the lifetime
of the component objects it contains. At design time, Visual
Studio provides a container that implements this interface.
Any component added to this container automatically
participates in code generation and gets its own member
variable in the user's code.

Note that it is possible to use the .NET Framework designer
architecture even if your objects are not components, but
there needs to be at least one object that is a component.
For example, if we were to expand our shape library into a
full vector drawing package, we would probably find that
emitting a member variable for each shape would not be
terribly efficient. Instead, it would probably make sense
for ShapeContainer to implement IComponent while individual
shapes did not. That requires more work on the component
vendor's part because less design-time logic is handled
automatically, but it is possible and may be an appropriate
choice for when the number of objects in the design surface
becomes huge.
An introduction to design-time

The .NET Framework was written with design-time support in
mind. What is design-time support? It's the ability to
connect several components together without writing code.
The .NET Framework was written to support very rich
design-time capabilities while allowing this design-time
specific code to reside in a separate assembly so it does
not contribute to the size of the runtime library.

Each object that implements the
System.ComponentModel.IComponent interface can have an
additional designer object associated with it. This object,
called a "designer", contains the additional code needed to
manipulate the object at design time. A designer may perform
a very simple task, such as hiding or changing properties on
the component that should not be available at design time,
or it may work with other designers to provide a visual
editor for a group of components, such as a form or web page
designer. A designer must implement the interface

There may be many designers created for a visual editor. One
of these designers must be the "master" that provides an
interface that the user can interact with. This designer is
called the "root designer", and the component it is bound to
is called the "root component". In the Windows Forms
designer, for example, the class System.Windows.Forms.Form
is typically the root component, while in ASP.Net it is

In addition these designers, there is an object that is
responsible for maintaining instances of all designers and
components, and for loading and saving data. This object
implements an interface called
System.ComponentModel.Design.IDesignerHost, and is usually
just called a "host" or "designer host". Visual Studio
provides an instance of this object for each visual editor.

As we delve more into the shape library's design time
support we will examine how its designers work in detail.

Persistence relates to the loading and saving of data. The
.NET Framework designer architecture allows data to be
persisted in any format. Visual Studio implements two common
formats: code generation and resource files.

Code generation is the default way that components save
their data. Because all components in the .NET Framework are
designed to work through command line compilers and standard
editors, they cannot rely solely on special features in
Visual Studio. Therefore, having Visual Studio generate
source code in response to changes to a visual editor is a
convenient way to provide rich design-time support while
minimizing the number of ways to implement a feature. In
addition, code generation acts as a great learning tool for
developers. Visual Studio provides no "magic"; developers
can see first-hand how everything fits together.

In addition to code generation, Visual Studio also provides
a way to save language-specific data and other resources
that cannot be easily represented as code (like bitmaps or
audio files, for example).

As we will see in some of the design time code contained in
the shape library, you have a great deal of control over how
resource and code generation support are handled for your
Shape library's design time experience

The following walk-through demonstrates the user model for
interacting with the shape library in Visual Studio. The
intent is that a user creates a class that derives from
ShapeContainer and uses this class to visually composite
several shapes together. She then compiles the project and
adds the newly created class to a Windows Forms form class.
The shapes then draw directly to the form.
Step 1: Creating a new ShapeContainer class

Visual Studio determines what designer to load based on the
class that your source file is inheriting from. We start off
by creating an empty class file, and then we change it to
inherit from Microsoft.Samples.ShapeLibrary.ShapeContainer.
This will enable the view designer button. Clicking on this
button shows the empty ShapeContainer designer, ready for

Notice that the designer has placed a disabled "MyShape"
item on the toolbox. This item refers to the current shape
we're creating; we'll use it later when we want to place
this shape on windows form.
Step 2: Adding shapes to the container

Next, the user uses the ellipse and line toolbox items to
create shapes. Shapes can be directly manipulated on the
shape container design surface. The designer provides
support for dragging and sizing shapes. Also, the property
browser shows the properties for each shape:
Step 3: Add the shape to a form

Next, the user compiles the project to make the MyShape
class available to other objects, and opens an empty form.
This enables the MyShape item on the toolbox, and disables
the ellipse and line shapes. The user drags the MyShape
toolbox item into the form. This creates an instance of
MyShape in the form's component tray (because MyShape is not
a control). But something interesting happens: MyShape is
drawn on the background of the form. ShapeContainer's
designer is performing this drawing, and we'll see how this
is accomplished in a later section:
Step 4: Run the application

Now the user presses F5 to run the application. This
displays the form, and the form is drawing the shape just
like we see at design time. This is exactly what the user
expects, but it does take some work to make this happen
because the shape container's designer had to generate the
code that binds the form's paint event to the shape
container's draw method:
Design time components

So, how does it all work? There are seven objects that make
up the design-time components for the shape library. All of
these objects are contained under the Design sub-directory
and have the namespace
"Microsoft.Samples.ShapeLibrary.Design". At the heart of
these objects is an object called the root designer. This
designer is associated with the ShapeContainer class through
a metadata attribute:

public class ShapeContainer : Shape {}

The root designer provides the visual editor that is shown
when the user double-clicks on the source file. As this is
the most important and visible portion of all of shape
library's design-time components, let's examine it first.

This designer provides the visual editor through the
IRootDesigner interface. The actual editing surface is
implemented as a Windows Forms control object. Painting
shapes onto the control is very easy - the designer simply
overrides the control's paint event and calls the shape
container's Draw method, passing the graphics object for the

In addition to painting the shapes, the root designer also
handles all user interaction. User interaction includes
three areas: mouse, toolbox and menus.
Mouse support

Mouse support is provided by the control class that resides
within the ShapeContainerRootDesigner. This control, called
DesignerView, listens to mouse events coming from Windows Forms.

A primary function of mouse support is hit-testing.
Hit-testing is the act of examining the current mouse
coordinates and determining if the mouse is hovering over
anything interesting. In our case, "interesting" is defined
as a shape or a grab handle. When the mouse hovers over a
shape, we want to change the cursor to a four-headed arrow
to indicate that the shape may be moved. When the mouse is
hovering over a grab handle, we want the cursor to reflect
the type of sizing that the grab handle allows. Our
DesignerView control knows where the mouse is because it
gets a MouseMove event each time the user moves the mouse.
Unfortunately, it has no idea where any of the shapes or
grab handles are located; shapes don't define any sort of
bounding rectangle and grab handles may be different for
each shape. That is where shape designers come in. For each
shape, there is an associated shape designer. The shape
designer provides public properties and methods that the
DesignerView object can call on. One of these methods is
called GetHitTest, which returns information about where the
mouse is in relation to the shape the designer is connected
to. This allows the DesignerView to deal with shapes in an
abstract way. The advantage of this should be obvious: if
another developer writes a new shape, she only needs to
provide an accompanying shape designer and the shape can be
immediately used.

The code for the mouse move logic is shown below:

protected override void OnMouseMove(MouseEventArgs me)
// Perform hit-testing of the shapes on the designer.
object newHitObject = null;
Shape newHitShape = null;

IDesignerHost host = DesignerHost;
if (host != null)
foreach(Shape s in m_designer.ShapeContainer.Shapes)
ShapeDesigner des = host.GetDesigner(s) as
if (des != null)
newHitObject = des.GetHitTest(me.X, me.Y);
if (newHitObject != null)
newHitShape = s;
Cursor = des.GetCursor(newHitObject);

The code simply looks for a shape designer for each shape in
the shape container's Shapes collection. If it finds one, it
asks that designer if the mouse coordinates are over the
shape. The value of newHitObject as returned from the
GetHitTest method is something that only the designer knows
how to interpret. Our control just uses this object in
future calls to the designer. This provides a nice degree of
isolation between the designers.
Toolbox support

Handing toolbox events is also important for our root
designer. The designer needs to accept shape objects from
the toolbox. The first order of business is to allow the
designer to limit what toolbox items are available. The
toolbox is a large repository of items and the designer
certainly cannot handle all item types. Instead, we want to
filter the set of items that are enabled for the user. We do
this by providing toolbox item filter attributes. We have
added these attributes to both the Shape class and to
ShapeContainerRootDesigner. If the filter attributes match,
then the toolbox item will be enabled. Here are the
attributes we provide on both classes:

public abstract class Shape : Component {}

internal class ShapeContainerRootDesigner :
ComponentDesigner, IRootDesigner {}

A toolbox item filter consists of two parameters. The first
parameter is some unique string that represents the name of
the filter. You can place any string here, but to avoid
collisions we have adopted a convention of using the
namespace of the class library you are building. If all
classes in the library descend from a common base class, we
also append this base class. So in our example, our filter
name is the fully qualified name of our Shape base class.

The second parameter declares the filter type and can be one
of four values:

"Allow" simply declares the existence of the filter, but
performs no other restrictions.
"Prevent" prevents the classes or designers with the
same filter name from showing up.
"Require" requires that both designer and class have the
filter name.
"Custom" dictates that the enabling of a toolbox item
will be determined at runtime by implementing the
IsSupported method on the IToolboxUser interface. Custom
should be used sparingly because it will slow down the
performance of your designer.

In the shape library code snippet above we have declared the
filter in such a way so shape items on the toolbox are only
enabled when the shape designer is showing, and the shape
designer itself will only allow shape items to be placed on it.

The table below shows the various permutations for filter
strings and filter types on both a designer and a class that
is on the toolbox.
Root Designer
Class Mismatch Allow Prevent Require Custom
Mismatch Y Y Y N Y
Allow Y Y N Y IsSupported
Prevent Y N N N N
Require N Y N Y IsSupported
Custom N IsSupported N IsSupported IsSupported

Y : The toolbox item will be enabled
N: The toolbox item will be disabled
IsSupported: The toolbox item will be enabled only if the
method IToolboxUser.IsSupported returns true.

Once we've successfully enabled the correct toolbox items,
we need to handle user requests to use them. There are three
different ways that a tool can be placed on a designer: the
user may double click the tool, she may use drag and drop
and drag the tool from the toolbox to the designer, or she
may click the tool, and then click on the designer. Each of
these techniques is handled differently by our root designer.

The simplest way to provide toolbox support is to handle a
double click that comes from the toolbox. This uses a direct
connection to your designer through an interface called
IToolboxUser. If your root designer implements this
interface, the ToolPicked method of the interface will be
called when the user double clicks on a toolbox item that
you support. ToolPicked is passed an instance of the toolbox
item that was chosen.

To provide support for drag and drop from the toolbox, your
designer's view must support OLE drag and drop. Because our
view is just a Windows Forms control, drag and drop support
is easy: we just have to set the AllowDrop property of the
control to true and add some drop handling code. This is
very easy thanks to the IToolboxService interface, which
provides rich interaction with the toolbox:

protected override void OnDragDrop(DragEventArgs e)

// Is this a toolbox item that is being dropped?
IToolboxService ts = ToolboxService;
if (ts != null && ts.IsToolboxItem(e.Data,
ToolboxItem item =
ts.DeserializeToolboxItem(e.Data, DesignerHost);

Note that toolbox items create their own components. If we
wanted to manipulate the components that the toolbox item
created, they are returned from the CreateComponents method
call. The actual code in ShapeContainerRootDesigner does
perform some manipulation of these components after creating

Finally, to provide support for clicking on the designer
surface and creating the currently selected tool on the
toolbox, we use additional methods of IToolboxService to
tell what the currently selected tool is:

protected override void OnMouseUp(MouseEventArgs e)

if (e.Button == MouseButtons.Left)
IToolboxService ts = ToolboxService;
if (ts != null &&
ts.GetSelectedToolboxItem(DesignerHost) != null) {
ToolboxItem item =

ShapeContainerRootDesigner provides one additional, and
uncommon, feature for the toolbox. When you open a shape in
the designer, it adds a toolbox item to the toolbox. This
toolbox item is disabled when the shape designer is visible,
but becomes enabled when other designers are active. This
toolbox item allows the developer to place an instance of
the shape container that is currently being developed in the
designer on the surface of another designer, similar to a
Windows Forms user control. This is accomplished by creating
a toolbox item that contains the class name of the class
we're currently designing, and adding it as a linked tool to
the toolbox. Linked tools are linked to a particular
designer, so they are automatically removed from the toolbox
when the designer's project is closed. All other tools on
the toolbox are saved into a global database and are always
available. The code to add a linked tool is very simple:

private void OnLoadComplete(object sender, EventArgs e)
IDesignerHost host = (IDesignerHost)sender;
host.LoadComplete -= new

// Now get a hold of the toolbox service and add an
icon for our user control. The
// toolbox service will automatically maintain this
icon as long as our file lives.
IToolboxService tbx =

if (tbx != null)
string fullClassName = host.RootComponentClassName;
ToolboxItem item = new ToolboxItem();
item.TypeName = fullClassName;

int idx = fullClassName.LastIndexOf('.');
if (idx != -1)
item.DisplayName =
fullClassName.Substring(idx + 1);
item.DisplayName = fullClassName;

item.Bitmap = new Bitmap(typeof(ShapeDesigner),

// Toolbox items are mutable until Lock is
called on them. This
// allows them to be very flexible without
requiring a bunch of
// different constructors. Once lock is called,
they are "fixed"
// and cannot be changed. After creating a
toolbox item you should
// always call Lock before handing it to the
toolbox service. Otherwise
// other people could change it on you.

// A "linked" toolbox item is one that is linked
to our designer. It
// follows our designer, rather than living
forever on the toolbox.
// The tool is automatically removed when the
project is closed, and
// re-added when the project is opened again.
tbx.AddLinkedToolboxItem(item, "Shapes", host);

Note that we do this work in an event handling method for
the LoadComplete event. Why? Because until we are done
loading the fully qualified name of the base class we're
designing isn't known.
Menu support

The shape designer also handles a few simple menu editing
commands: cut, copy, paste and delete. In Visual Studio, a
"command" is a user request, be it a menu item, toolbar
button, or keystroke. This means that by handling the delete
command, we support not just the delete menu item but also
the toolbar button and the delete key.

There are two parts to each command in Visual Studio: the
definition of the command, and the implementation. There is
only one definition for each command, but there may be many
implementations. Using delete as an example, the delete
command always appears on the same place on the menu and has
the same help text associated with it. The actual code that
performs the delete command is different for the text editor
than it is for a designer. The .NET Framework designer
architecture allows you to implement any command that is
already defined. To define a new command, however, you must
have the Visual Studio Integration Package (VSIP) SDK.

Implementing a command through the .NET Framework designer
architecture is easy. You simply provide an event handler
that will be called when the command is invoked. To do this,
you create a MenuCommand object, and pass this object to the
IMenuCommandService interface. A MenuCommand object consists
of two pieces of information: an event handler to be invoked
when the user executes the command, and a CommandID object
that indicates what command you are handling. The class
System.ComponentModel.Design.StandardCommands contains a set
of CommandID objects for many common commands. If you need
to handle a command that is not listed you may do so by
creating a new CommandID object.

Implementing clipboard functionality is also quite easy in
the .NET Framework designer architecture. To place an item
on the clipboard, you must save that item into some form
that can be recreated. This process is called serialization.
Many objects in the framework support serialization, but
some, such as controls and web components, may not. These
objects are designed to use design-time serialization, which
typically involves the generation of source code, to save
their state. Storing these objects onto the clipboard could
be very difficult if it weren't for a handy service called
IDesignerSerializationService. This service takes a
collection of objects and returns a single object. This
object can always be serialized through the standard .NET
Framework serialization mechanisms, which means it can be
placed directly on the clipboard. The collection of objects
passed to IDesignerSerializationService can be objects that
already support serialization, or objects that support code
generation. The copy command implemented in the
ShapeContainerRootDesigner shows how easy this is to use:

private void OnMenuCopy(object sender, EventArgs e)
// What is this? Components typically do not
support serialization, but they all
// support being saved in a designer. How this save
is accomplished is dependent
// on what is hosting the designer. Whatever
environment that is hosting us
// provides a service called
IDesignerSerializationService. This service can
// take an arbitrary collection of objects and
convert them to an object
// that can be serialized. The object that comes
out of a Serialize call
// on this service can then be passed to the
clipboard, or through a
// drag and drop operation.
IDesignerSerializationService ds =

if (ds != null)
object serializedData =
DataObject data = new
DataObject("ShapeLibraryData", serializedData);
Clipboard.SetDataObject(data, true);

Now that we've covered the root designer, let's dig into the
designers that are created for each shape on the shape
container's design surface. These designers are smaller
because they only provide shape-specific functionality.

The ShapeDesigner class is the base class for all things
that are derived from Shape. It inherits from
System.ComponentModel.Design.ComponentDesigner, which
implements IDesigner. The shape designer class is abstract
and defines several properties and methods that deriving
classes must implement. The reason why this has so many
abstract methods is because the Shape object itself provides
nearly no functionality. There are no common properties, so
in order to treat shapes in a consistent fashion a

Is This Answer Correct ?    0 Yes 0 No

Post New Answer       View All Answers

Please Help Members By Posting Answers For Below Questions

Explain the difference between server.transfer and response.redirect?


how to update text box value in project?


no.of pages comes before protected void ?


Explain how do you initiate a string without escaping each backslash?


What is asp language?


What is the command to display characters to the html page in asp?


Define clientcertificate collection?


Explain the difference between inline and code behind.


What is the difference between asp and html? Or why asp is better than html?


What is the work of asp?


What are the stored procedure and why they are needed?


What type of code is found in a code-behind class?


What is use of asp?


What is asp what can asp do for you?


sir,please send me the NIC exam questions