XP Style Navigation Bar Server Control with collection property and embedded resources






4.87/5 (12 votes)
Oct 13, 2007
6 min read

77502

1000
An article that explains how to create a custom server control with collection property and embedded resources
Index
- Introduction
- Why this Article?
- Introduction to ASP.NET Server Controls
- Class Diagram
- NavigationBar Members
- NavigationBarItemsCollection Class
- Setting Collections to Property
- NavigationBarItemBuilder Class
- Embedding Resources with Control
- Retrieving from Embedded Resource
- Looking into AssemblyInfo.cs
- JavaScript for Expanding/Collapsing menu
- Known Issues with this Control
- Conclusion
Introduction
This article explains how to create an ASP.NET server control which has a collection
property and uses embedded web resources. In this, we will be creating an XP look and feel navigation server control. This article will focus on:
- How to create a server control with
collection
property - Show
collection
editor on the designer forcollection
property - Implement Web Resources concept

Why this Article?
Why am I writing this control? Creating server control with properties is not at all a tough job. But creating a control which has a collection <code>
property requires a few steps. I have not found any good examples that manage with collection
properties and design time support. This article focuses on creating collection
classes and adding the collection
items from Visual Studio Designers collection
editor.
A custom server control should be always easy to use like other ASP.NET controls. Many custom controls use JavaScripts and images, and instruct the users to copy those to a location on the server to get the control working. In this article, I will explain how this can be avoided by embedding resources in the Assembly.
Introduction to ASP.NET Server Controls
This article is not a step by step explanation of creating a server control. That has been written by several writers before. If you are reading this article without any prior knowledge of ASP.NET Custom Server Controls, I refer you to read this before you continue reading this article.
ASP.NET allows developing custom reusable controls. These controls are inherited from System.Web.UI.WebControl
. When a new control library project is created, Render()
method in WebControl
class will be overridden. ASP.NET processes each control in the page and asks them to render by calling the Render()
method of control. Render()
method takes HTMLTextWriter
object and writes rendered HTML to the response. In this example, I have also overridden the OnInit()
method to register the startup client side scripts.
Class Diagram

NavigationBar Members
Name | Description | |
![]() |
Collapsed |
Indicates whether the control has to be collapsed or expanded |
![]() |
HeaderCssClass |
Style sheet class name for the header text |
![]() |
HeaderFont |
Font name for the header text |
![]() |
HeaderFontSize |
Specifies header font size |
![]() |
HeaderForeColor |
Specifies color of the header text |
![]() |
HeaderText |
Menu header text. By default this will be "Menu Header" |
![]() |
Items |
Collection of NavigationBarItem objects |
![]() |
ItemsBgColor |
Background color of items cell |
![]() |
ItemsCssClass |
Style sheet class for items |
![]() |
ItemsFont |
Font name for navigation bar item |
![]() |
ItemsFontSize |
Font size for navigation bar item |
![]() |
MenuItemSpace |
Space between each menu item |
![]() |
PanelColor |
Color of the menu container. By default this will be XP blue color |
![]() |
SpacerWidth |
Width between left image and menu item text |
NavigationBarItems Collection Class
Collection
class holds similar types of objects which are accessible using an index. .NET allows different methods to create collection
classes. NavigationBarItemsCollection
class holds NavigationBarItem
objects. This collection
class implements ICollection
and IList
interfaces, which forces a class to implement collection
functionality. Objects are kept inside an ArrayList
. The following code snippet shows common functions used in this collection
class.
public int Add(NavigationBarItem item)
{
return this._Items.Add(item);
}
public void Clear()
{
this._Items.Clear();
}
public void RemoveAt(int index)
{
this._Items.RemoveAt(index);
}
public int Count
{
get
{
return this._Items.Count;
}
}
To make collection
members accessible through an index, the following property is used:
public NavigationBarItem this[int index]
{
get
{
return (NavigationBarItem)this._Items[index];
}
set
{
this._Items[index] = (NavigationBarItem)value;
}
}
This enables a programmer to access NavigationBarItem
object from the collection
as follows:
NavigationBarItem item = NavigationBar1.Items[1];
Setting Collection Class to Property
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
Editor(typeof(System.ComponentModel.Design.CollectionEditor),
typeof(System.Drawing.Design.UITypeEditor)),
PersistenceMode(PersistenceMode.InnerDefaultProperty), MergableProperty(false)]
public NavigationBarItemsCollection Items
{
get { return _Items; }
}
Simply setting collection
class to property won't work correctly in VSDesigner. It will show System.Object
when a new item is added through the collection editor. But using code this can be added.
To add items through design view, we need the below attributes to be specified:
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
Editor(typeof(System.ComponentModel.Design.CollectionEditor),
typeof(System.Drawing.Design.UITypeEditor)),
PersistenceMode(PersistenceMode.InnerDefaultProperty), MergableProperty(false)]
DesignerSerializationVisibilityAttribute
is used to serialize a property on design time. For more information on the attribute, please check MSDN documentation. PersistenceMode
is another attribute which tells how a property should be on a page. PersistenceMode.InnerDefaultProperty
tells ASP.NET to persist the items as inner tags.
To set this, a class that inherits ControlDesigner
is needed. ControlDesigner
is the base class which helps to extend design time behavior of a web control. NavigationBarDesigner
is a derived class from ControlDesigner
. The following snippet shows the overridden Initialize()
method.
public override void Initialize(System.ComponentModel.IComponent component)
{
base.Initialize (component);
this._NavigationBar = (NavigationBar)component;
}
NavigationBarItemBuilder Class
This class is derived from ControlBuilder
class. Most controls in ASP.NET will be associated with ControlBuilder
class, which helps to parse both control and its inner tags. NavigationBarItemBuilder
overrides methods like AllowWhitespaceLiterals()
and HtmlDecodeLiterals()
. AllowWhitespaceLiterals()
parses white space in control tag content provided a true
value is returned. This method always returns true value. So the functionality has been overridden to return a false
value. HtmlDecodeLiterals()
is overridden to decode HTML characters found on tag content. Check the following snippet:
public override bool AllowWhitespaceLiterals()
{
return false;
}
public override bool HtmlDecodeLiterals()
{
return true;
}
Embedding Resources with Control
I have seen many custom controls with usage guidelines like:
- Copy images to images folder on server
- Copy js files to include directory on server, etc.
Embedding resources with control is a concept that helps to create a variety of server controls without these prerequisites.
Problems with Control Usage Guidelines
In ASP.NET 1.1, the external resources like stylesheets, JavaScript files are deployed in a package and installed in the client machine, which stop functioning when these files are saved in the incorrect location.
WebResource concept in ASP.NET 2.0 overcame all these problems, so that, all these external resources can be embedded with the assembly and loaded at runtime. While running a page with NavigationBar
control, a reference to WebResource.axd can be seen from page's source code, which handles these embedded resources. The querystring
variables represent time stamp value and requested resource name. To embed a file, set build action of the file to "Embedded resource". The following image explains how web resources are working.

Retrieving from Embedded Resource
EmbeddedResourceManager
is a class which manages all embedded resources. The following snippet shows retrieving header image from an embedded resource.
public string HeaderBackground
{
get
{
string BgUrl = _NavigationBar.Page.ClientScript.GetWebResourceUrl
(_NavigationBar.GetType(),
"System.Web.UI.WebControls.headerbg.gif");
return BgUrl;
}
}
Page.ClientScript.GetWebResourceUrl
is used to get the embedded resources URL. GetWebResourceUrl()
returns the temporary URL for the resource.
Looking into AssemblyInfo.cs
This section deals with adding embedded resources details in AssemblyInfo.cs file.
[assembly: TagPrefix("System.Web.UI.WebControls", "W3Hearts")]
The above statement is used to set the tagprefix
for the control. Here is an example for tagprefix
.
<W3Hearts:NavigationBar id=NavigationBar1 runat="server">
</W3Hearts:NavigationBar>
Page level tag prefix can be modified by the user. When custom controls are added, Visual Studio editor generates a similar tag in the page header.
<%@ Register Assembly="NavigationBar" Namespace="System.Web.UI.WebControls"
TagPrefix="W3Hearts" %>
The following code is used for the embedded resources:
[assembly: System.Web.UI.WebResource
("System.Web.UI.WebControls.NavigationBar.js",
"text/js", PerformSubstitution = true)]
[assembly: System.Web.UI.WebResource
("System.Web.UI.WebControls.headerbg.gif", "image/gif")]
[assembly: System.Web.UI.WebResource
("System.Web.UI.WebControls.downarrow.gif", "image/gif")]
[assembly: System.Web.UI.WebResource
("System.Web.UI.WebControls.left1.gif", "image/gif")]
[assembly: System.Web.UI.WebResource
("System.Web.UI.WebControls.spacer.gif", "image/gif")]
[assembly: System.Web.UI.WebResource
("System.Web.UI.WebControls.uparrow.gif", "image/gif")]
This specifies the resource name and its type. The resource name should start with the default namespace. This method fails when embedded resources are in subfolders.
JavaScript for Expanding/Collapsing Menu
This control uses NavigationBar.js file for JavaScript functions, which contains the function intended to Expand/Collapse navigation bar. The top and bottom arrow on the right side of the control is loaded from the embedded resource. The following example shows how to retrieve the embedded resource URL in a JavaScript function:
function Toggle(obj,NavigationBarId)
{
if(document.getElementById(obj).style.display == 'none')
{
document.getElementById(obj).style.display = 'block';
document.getElementById(NavigationBarId + "_Arrow").src =
'';
}
else
{
document.getElementById(obj).style.display = 'none';
document.getElementById(NavigationBarId + "_Arrow").src =
'';
}
}
Known Issues with this Control
ViewState
managing problem forNavigationBarItems
- Lack of binding data directly from a
Datasource
Conclusion
In this article, we dealt with creating custom server control with collection property and embedded resources. Collection property holds a collection of NavigationBarItem
objects which can be added from design view.
WebResource
is a new concept in ASP.NET 2.0 which helps control developers to use these controls without deploying resource files separately.