Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / ASP.NET

A Custom Dialog Box Control

4.70/5 (23 votes)
22 Oct 2005CPOL6 min read 1   3K  
An article on creating a templated control in ASP.NET 2.0.

Sample Image

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:

  1. Expose a public property of type ITemplate, like so:
    C#
    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;}
        }
    }
    
  2. Create the template from within the overridden CreateChildControls method:
    C#
    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:

C#
[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.

C#
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:

HTML
<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):

HTML
<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.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)