Introduction
This articles provides a nice Office look-alike dialog box for ASP.NET 2.0. I created this control as an exercise in developing templated controls in .NET 2.0. The code uses a custom designer, as well as the new GetWebResourceUrl
methods in the System.Web.UI
namespace. The control is a useful supplement when creating web pages with AJAX behaviour, as well as it looks quite nice.
The DialogBox class
Class diagram. Click to enlarge.
| The DialogBox class has the following properties:
Resizable - determines if the control can be resized by the user Moveable - determines if the control can be moved by the user InitialDisplayStyle - An enum that describes the state of the control when the page is loaded Text - caption for the dialog box
The DialogBox class has two methods:
CreateChildControls - overridden from the base class. All child controls of a composite control should be created from within this method. The method is called by the runtime to render the control. GetDesignTimeHtml - an internal method, used by the designer to force the correct rendering of the control in design-time.
|
The control also overrides the base OnInit
method and the Tagkey
property, in order to render the JavaScript necessary, and the Tagkey
property to make sure that our control is rendered as a <div>
tag.
I've chosen to inherit my DialogClass
from the CompositeControl
class. The CompositeControl
class is a new class in .NET 2.0, specially created for creating custom controls with child controls. It takes care of such things as assuring that the child controls are created if the control consumer attempts to use the FindControl
method and the Controls
collection. It also implements the INamingContainer
interface, assuring that all child controls will have unique ClientIDs.
What's special about templated controls
If you've ever used ASP.NET, you have probably used templated controls, possibly without knowing it. The DataGrid
, Repeater
or DataList
controls are prime examples of templated controls. A templated control allows the developer to render custom HTML or even its own ASP.NET controls within the templated control. Creating a templated control is done in two steps:
- Expose a public property of type
ITemplate
, like so:
public class DialogBox : System.Web.UI.WebControls.CompositeControl
{
private ITemplate containerTemplate;
private Control containerControl;
[Browsable(false),
PersistenceMode(PersistenceMode.InnerProperty)]
public virtual ITemplate ItemTemplate
{
get {return containerTemplate;}
set {containerTemplate = value;}
}
}
- Create the template from within the overridden
CreateChildControls
method:
containerControl = new Control();
if (ItemTemplate != null)
{
ItemTemplate.InstantiateIn(containerControl);
}
else
{
containerControl.Controls.Add(new LiteralControl(Text));
}
The else
- code block is there just so that the control displays something when it is added to the page, before the user creates a template for the dialog box. If no template has been created, the control will render the caption in the content area.
Using GetWebResourceUrl
A cool new feature in ASP.NET 2.0 is the ability to create resources that are compiled into the control itself. ASP.NET 2.0 comes with a new HTTP handler, "WebResource.axd". This is somewhat similar to the Trace.axd handler, but this handler can be used to access any static resource in your control project, for example, an image, a JavaScript file, a sound, or whatever you desire to compile into your project. This new feature makes life a whole lot easier for control developers, as versioning of external files becomes much easier. Using the GetWebResourceUrl
is somewhat tricky, and involves three steps.
First, add your resource to the project. Set build action in the Properties pane for the file to Embedded resource.
Second, add your resource to the AssemblyInfo.cs file of the project, like so:
[assembly: WebResource("WebControls.Resources.header_decoration.gif", "image/gif")]
The first parameter of the WebResource
attribute is the fully qualified name of the resource. The MSDN documentation does not mention this, but you have to prefix the filename (header_decoration.gif) with the assembly name (WebControls
), and the folder which it resides in (Resources). The second parameter is the MIME type which your resource should return to the browser.
Third, add code to your page to generate the special URL required to access the resource.
imgHeaderDeco = new Image();
imgHeaderDeco.ImageUrl = Page.ClientScript.GetWebResourceUrl(
typeof(DialogBox),
"WebControls.Resources.header_decoration.gif");
The output generated on the web page should look something like this:
<img src="http://www.codeproject.com/WebSite2/WebResource.axd?
d=E1Khv7nbIwG5fSPcsXnzTP4Bukco5S0XUA0FBsHzjTskoXfzMVF14ZAlK7adsv
PsJgALtyt5nqpSESM7tDVIZA2&t=632651830942047145" />
The designer
The DialogDesigner
class is derived from the CompositeControlDesigner
class. The base class is another new addition to .NET 2.0, which makes creating templated controls much easier than it was in previous versions of the .NET framework. The designer is necessary in order to get correct design-time behaviour of the control.
Using the code
Using the code is pretty straightforward; just add the control to your toolbox, drag it on a web page, and it is up and running. In order to set the template from design view, click the small arrow near the top right side of the dialog box, and choose "Edit template". Or, in source view, enter something similar to this (marked with bold text):
<fwc:DialogBox ID="DialogBox1" runat="server" Height="33px"
Width="202px" Resizable="True" Text="A custom dialogbox"
InitialDisplayState="ShowingDialog">
<ItemTemplate>
<center><b>Hello, world!</b></center>
</ItemTemplate>
</fwc:DialogBox>
<a href="javascript:ShowDLG('<%=DialogBox1.ClientID%>'">Show dialog</a>
<a href="javascript:HideDLG('<%=DialogBox1.ClientID%>'">Hide dialog</a>
Inside the ItemTemplate
tag, you can enter any valid HTML, as well as ASP.NET server controls. Note: If you use ASP.NET server controls, they can be re-found using the FindControl
method of the dialog box instance. They will also persist state during postback. As you also can see from the code snippet above, the dialog box JavaScript has two methods: ShowDLG
for displaying a dialog box, and HideDLG
for hiding it.
Further development
Currently, the control does not persist state position or display state between postbacks. My intent is to use the control on AJAX-pages, so postback is not an issue. However, I am considering implementing it in a future release.
The control is tested and found working on IE 6 and Mozilla 1.5. It does not render 100% correctly in Mozilla, but I haven't bothered investigating it yet.
If I can find the time, I would like to add some more JavaScript functionality, especially to manipulate the control with JavaScript code, set the caption, move it, open in centered on the screen, etc.
I have just started to look at skinning, so currently this control is not very flexible with respect to that.
Also, I am not quite happy with the designer. It displays the control correctly, but since it always is rendered in the opened state in the designer, it can block access to other controls when in design view. One solution would be to add an action verb (Show/hide control) to the designer class, and render the correct HTML or a block (for instance, like UserControls were rendered under ASP.NET 1.0), depending on the selection of the action verb.
If you have a feature you would like to see in a future release, please let me know, and I will see what I can do.
Points of Interest
If you are interested in designing custom controls, I recommend reading Nikhil Kohtari's book Developing Microsoft ASP.NET Server Controls and Components. It's a great read on how to create custom controls.
History
- 10/18/2005 - First version.