Walkthrough: Creating a Basic Control Designer for a Web Server Control

This walkthrough demonstrates how to create a basic control designer to provide a design-time user interface (UI) for a Web server control.

When you create a custom ASP.NET server control, you can create an associated designer to render the control in a visual design tool such as Microsoft Visual Studio 2005. The designer enables the host environment to render a design-time UI for the control, so that developers can easily configure the control's properties and content. For more information about designer features and the various designer classes you can associate with a custom control, see ASP.NET Control Designers Overview.

During this walkthrough, you will learn how to:

  • Create a standard composite control designer and associate it with a composite control.

  • Create a resizable composite control designer and associate it with a composite control.

  • Create a basic container control designer with an editable region, and associate it with a WebControl control. This designer enables you to add text to the editable region on the design surface, and you can also drag additional controls into the region.

  • Reference the custom controls (and their associated designers) on a Web page.

  • Work with the Web page in Design view in Visual Studio 2005.

Prerequisites

In order to complete this walkthrough, you will need:

  • Visual Studio 2005, which you will use to create a Web page that hosts your custom controls and their associated designers.

  • An ASP.NET Web site, for the page that hosts the controls. If you have a site already configured, you can use that site as a starting point for this walkthrough. Otherwise, for details on creating a virtual directory or site, see How to: Create and Configure Virtual Directories in IIS 5.0 and 6.0.

Creating Custom Controls and Designers

In this section, you create three basic Web server controls and an associated custom control designer for each of them.

To create a file for the code

  1. In an editor, create a new file named SimpleControlDesigners with the appropriate extension for the language you are working in. For example, in Visual Studio 2005, create a new class file named SimpleControlDesigners.vb or SimpleControlDesigners.cs.

  2. Add the following namespace references that are necessary for working with the designer classes. Also add a namespace to contain your controls and the associated designers.

    Imports System
    Imports System.ComponentModel
    Imports System.ComponentModel.Design
    Imports System.Drawing
    Imports System.Web.UI
    Imports System.Web.UI.Design
    Imports System.Web.UI.Design.WebControls
    Imports System.Web.UI.WebControls
    
    Namespace Samples.AspNet.VB.Controls
    EndNamespace
    
    using System;
    using System.ComponentModel;
    using System.ComponentModel.Design;
    using System.Drawing;
    using System.Web.UI;
    using System.Web.UI.Design;
    using System.Web.UI.Design.WebControls;
    using System.Web.UI.WebControls;
    
    namespace Samples.AspNet.CS.Controls 
    {
    }
    
  3. Save the file.

Now you are ready to create a composite Web server control and an associated designer. A designer can be in the same assembly as the control or in a different one; in this walkthrough, you create them in the same code file and assembly for convenience.

To create a composite control and an associated designer

  1. Within the namespace you declared in the SimpleControlDesigners file, create a public declaration for a composite control class that inherits from CompositeControl, as shown in the following code example.

    PublicClass SimpleCompositeControl
            Inherits CompositeControl
        EndClass
    
    publicclass SimpleCompositeControl : CompositeControl
        {
        }
    
  2. Add the public properties shown in the following code example to the class. These will be used to create part of the UI on the Web page.

    Dim _prompt AsString = "Please enter your date of birth: "OverridableProperty Prompt() AsStringGetDim o AsObject
            o = ViewState("Prompt")
            If o IsNothingThenReturn _prompt
            ElseReturnCType(o, String)
            EndIfEndGetSet(ByVal value AsString)
            ViewState("Prompt") = value
        EndSetEndPropertyOverridableProperty DOB() As DateTime
        GetDim o AsObject
            o = ViewState("DOB")
            If o IsNothingThenReturn DateTime.Now
            ElseReturnCType(o, DateTime)
            EndIfEndGetSet(ByVal value As DateTime)
            ViewState("DOB") = value
        EndSetEndProperty
    
    private String _prompt = "Please enter your date of birth: ";
    publicvirtual String Prompt
    {
        get
        {
            object o = ViewState["Prompt"];
            return (o == null) ? _prompt : (string)o;
        }
        set
        {
            ViewState["Prompt"] = value;
        }
    }
    
    publicvirtual DateTime DOB
    {
        get
        {
            object o = ViewState["DOB"];
            return (o == null) ? DateTime.Now : (DateTime)o;
        }
        set
        {
            ViewState["DOB"] = value;
        }
    }
    
    
  3. Create a method to add child controls to the composite control. The following method adds two text boxes and a line break that will be visible on the Web page.

    ProtectedOverridesSub CreateChildControls()
        Dim lab AsNew Label
    
        lab.Text = Prompt
        lab.ForeColor = System.Drawing.Color.Red
        Me.Controls.Add(lab)
    
        Dim lit AsNew Literal()
        lit.Text = "<br />"Me.Controls.Add(lit)
    
        Dim tb AsNew TextBox()
        tb.ID = "tb1"
        tb.Text = DOB.ToString()
        Me.Controls.Add(tb)
    
        MyBase.CreateChildControls()
    EndSub
    
    protectedoverridevoid CreateChildControls() 
    {
        Label lab = new Label();
    
        lab.Text = Prompt;
        lab.ForeColor = System.Drawing.Color.Red;
        this.Controls.Add(lab);
    
        Literal lit = new Literal();
        lit.Text = "<br />";
        this.Controls.Add(lit);
    
        TextBox tb = new TextBox();
        tb.ID = "tb1";
        tb.Text = DOB.ToString();
        this.Controls.Add(tb);
    
        base.CreateChildControls();
    }
    
  4. Create a simple composite control designer class that derives from CompositeControlDesigner to associate with the composite control you just created.

    Although there are a variety of UI rendering features you could add to the designer, the following code example simply creates the designer and overrides a key property in the base class to prevent the control from being resized in design view.

    PublicClass SimpleCompositeControlDesigner
        Inherits CompositeControlDesigner
        ' Set this property to prevent the designer from being resized.PublicOverridesReadOnlyProperty AllowResize() AsBooleanGetReturnFalseEndGetEndPropertyEndClass
    
    publicclass SimpleCompositeControlDesigner : CompositeControlDesigner
    {
        // Set this property to prevent the designer from being resized.publicoverridebool AllowResize 
        {
            get { returnfalse; }
        }
    }
    
  5. Immediately above the class declaration for the composite control, add a Designer metadata attribute that associates the control with the designer class you just created, as shown in the following code example.

    <Designer(GetType(SimpleCompositeControlDesigner))> _
    PublicClass SimpleCompositeControl
        Inherits CompositeControl
    
    [Designer(typeof(SimpleCompositeControlDesigner))]
    publicclass SimpleCompositeControl : CompositeControl
    
  6. Save the file.

Now that you have created a custom composite Web server control and an associated designer, you can create a second control that derives from the first. The second control differs only in that its associated designer can be resized on the design surface.

To create a resizable composite control and associated designer

  1. Within the namespace you declared in the SimpleControlDesigners file, create a public declaration for a new composite control class that inherits from the SimpleCompositeControl control you created earlier. The following code example demonstrates a new declaration.

    PublicClass SimpleCompositeControl2
            Inherits SimpleCompositeControl
        EndClass
    
    publicclass SimpleCompositeControl2 : SimpleCompositeControl
        {
        }
    
  2. Associate this control with the CompositeControlDesigner base class.

    By default, this example creates a basic, resizable designer for the composite control.

    <Designer(GetType(CompositeControlDesigner))> _
    PublicClass SimpleCompositeControl2
        Inherits SimpleCompositeControl
    EndClass
    
    [Designer(typeof(CompositeControlDesigner))]
    publicclass SimpleCompositeControl2 : SimpleCompositeControl
    {
    }
    
  3. Save the file.

The first two controls you created were composite controls that you associated with composite control designers. Now you will create a simple control that derives from WebControl, and associate it with a ContainerControlDesigner class. This type of designer is useful when you want to associate a designer with a single custom Web server control and provide a single editable region on the design surface. The custom control you create here does not implement any actual functionality; it exists only to show the features of the ContainerControlDesigner class.

Note

You could also provide this same functionality using a composite control and designer like those you created earlier. This example is intended only to show how you can use the ContainerControlDesigner class and associate it with a WebControl control.

To create a Web server control and a container designer with an editable region

  1. Within the namespace you declared in the SimpleControlDesigners file, create a public declaration for a new Web server control class, as shown in the following code example.

    PublicClass SimpleContainerControl
            Inherits WebControl
            Implements INamingContainer
        EndClass
    
    publicclass SimpleContainerControl : WebControl, INamingContainer
        {
        }
    
  2. Create a container control designer class to associate with the custom control. Implement two properties: a FrameStyle property to contain the style for the designer's frame, and a FrameCaption property to contain the frame's header text. These properties provide a frame for the control to be visibly rendered and selected on the design surface. The code for the designer and properties is shown in the following code example.

    Note

    The ContainerControlDesigner class automatically handles all other aspects of rendering the custom control at design time and providing a single editable region.

    PublicClass SimpleContainerControlDesigner
        Inherits ContainerControlDesigner
    
        Dim _style As Style
    
        ' Add the caption by default.PublicOverridesReadOnlyProperty FrameCaption() AsStringGetReturn"A Simple ContainerControlDesigner"EndGetEndPropertyPublicOverridesReadOnlyProperty Framestyle() As Style
            GetIf _style IsNothingThen
                    _style = New Style()
                    _style.Font.Name = "Verdana"
                    _style.Font.Size = New FontUnit("XSmall")
                    _style.BackColor = Color.LightBlue
                    _style.ForeColor = Color.Black
                EndIfReturn _style
            EndGetEndPropertyEndClass
    
    publicclass SimpleContainerControlDesigner : ContainerControlDesigner
    {
        private Style _style = null;
    
        // Add the caption by default. Note that the caption // will only appear if the Web server control // allows child controls rather than properties. publicoverridestring FrameCaption
        {
            get
            {
                return"A Simple ContainerControlDesigner";
            }
        }
    
        publicoverride Style FrameStyle
        {
            get
            {
                if (_style == null)
                {
                    _style = new Style ();
                    _style.Font.Name = "Verdana";
                    _style.Font.Size = new FontUnit ("XSmall");
                    _style.BackColor = Color.LightBlue;
                    _style.ForeColor = Color.Black;
                }
    
                return _style;
            }
        }
    }
    
  3. Associate the designer with the control. Immediately above the class declaration for the Web server control, add the Designer metadata attribute. Note that in this case, as shown in the following code example, you also add the ParseChildren attribute with a false parameter. This tells the design-time parser to treat the inner contents of controls as child controls, rather than as properties. In this case, you want to treat the inner contents of this control as child controls so that you can actually drag other server controls into the editable region at design time, and edit their properties as well.

    <Designer(GetType(SimpleContainerControlDesigner))> _
    <ParseChildren(False)> _
    PublicClass SimpleContainerControl
        Inherits WebControl
        Implements INamingContainer
    EndClass
    
    [Designer (typeof(SimpleContainerControlDesigner))]
    [ParseChildren (false)]
    publicclass SimpleContainerControl : WebControl, INamingContainer
    {
    }
    
  4. Save the file.

You have created three custom controls and associated control designers with them. All that remains is to compile the controls into an assembly and then work with them in a visual design tool.

To compile the custom controls and designers

  1. Open a command prompt to the folder where you created the SimpleControlDesigners file. From this prompt, you can compile the source code into an assembly.

    Note

    To run the .NET Framework compilers from this location, you must have already added the path of your .NET Framework installation to your computer's PATH variable. Usually, this path is under the Windows installation directory at \Microsoft.NET\Framework\<version number>. If you have not updated the PATH variable, right-click My Computer, select Properties, click the Advanced tab, and click the Environment Variables button. In the System Variables list, double-click the PATH variable. In the Variable value text box, add a semicolon to the end of the existing values in the text box, and then type in the path of your .NET Framework installation. Click OK to close each dialog box.

  2. Compile the controls in the SimpleControlDesigners file into an assembly using the following compile command.

    csc /r:System.dll /r:System.Design.dll /r:System.Drawing.dll /debug+ /r:System.Web.dll /t:library /out:SimpleControlDesignersCS.dll simplecontroldesigners.cs
    
    vbc /r:System.dll /r:System.Design.dll /r:System.Drawing.dll /debug+ /r:System.Web.dll /t:library /out:SimpleControlDesignersVB.dll SimpleControlDesigners.vb
    
  3. Move the resulting assembly file to the \Bin folder of the Web site for the page that will host your controls.

    Note

    Visual Studio users who want to compile the controls and designers need to add a reference to System.Design.dll. For more information, see How to: Add a Reference to a .NET or COM Component in a Web Site.

Creating a Web Page to Host the Controls

Now that you have created an assembly with your custom controls and their associated control designers, you will create a Web page in Visual Studio 2005 to reference the controls, see how they appear in Design view, and load the page in a browser.

To create a Web page to host the controls

  1. With your Web site open in Visual Studio 2005, create a new page called ControlDesigners.aspx. At the top of the page, just under the page declaration, add a Register directive to reference the assembly and controls you created previously, as shown in the following code example.

    <%@ Page Language="VB" %>
    <%@ register tagprefix="aspSample" 
      assembly="SimpleControlDesignersVB" 
      namespace="Samples.AspNet.VB.Controls" %>
    
    <%@ Page Language="C#" %>
    <%@ register tagprefix="aspSample" 
      assembly="SimpleControlDesignersCS"namespace="Samples.AspNet.CS.Controls" %>
    
  2. Complete the rest of the page as shown in the following code example, to reference each of the three controls you created previously: SimpleCompositeControl, SimpleCompositeControl2, and SimpleContainerControl. Note that to reference each control, you use the aspSample prefix specified in the Register directive.

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml" >
    <head runat="server">
        <title>Designers Page</title>
    </head>
    <body>
        <form id="form1" runat="server">
        <div>
            <p style="font-family:tahoma;font-size:large;
                font-weight:bold">
                Simple Control Designers
            </p>
            <div style="font-family:tahoma;font-size:x-small;">
                <span style="font-size: 14pt">
                Composite, no-resize</span>
            </div>
            <aspSample:SimpleCompositeControl id="SimpleControl1" runat="server" />
            <br /><br />
            <div style="font-family:tahoma;font-size:x-small;">
                <span style="font-size: 14pt">
                Composite, resize</span>
            </div>
            <aspSample:SimpleCompositeControl2 id="SimpleControl2" runat="server"  
                height="87px" width="238px" />
            <br /><br />
            <div style="font-family:tahoma;font-size:x-small;">
                <span style="font-size: 14pt">
                    Container</span>
            </div>
            <aspSample:SimpleContainerControl id="SimpleControl3" runat="server" 
                height="57px">
                Type some content here.
            </aspSample:SimpleContainerControl>
            <br /><br />
        </div>
        </form>
    </body>
    </html>
    
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml" >
    <head runat="server">
        <title>Designers Page</title>
    </head>
    <body>
        <form id="form1" runat="server">
        <div>
            <p style="font-family:tahoma;font-size:large;
                font-weight:bold">
                Simple Control Designers
            </p>
            <div style="font-family:tahoma;font-size:x-small;">
                <span style="font-size: 14pt">
                Composite, no-resize</span>
            </div>
            <aspSample:SimpleCompositeControl id="SimpleControl1" runat="server" />
            <br /><br />
            <div style="font-family:tahoma;font-size:x-small;">
                <span style="font-size: 14pt">
                Composite, resize</span>
            </div>
            <aspSample:SimpleCompositeControl2 id="SimpleControl2" runat="server"  
                height="87px" width="238px" />
            <br /><br />
            <div style="font-family:tahoma;font-size:x-small;">
                <span style="font-size: 14pt">
                    Container</span>
            </div>
            <aspSample:SimpleContainerControl id="SimpleControl3" runat="server" 
                height="57px">
                Type some content here.
            </aspSample:SimpleContainerControl>
            <br /><br />
        </div>
        </form>
    </body>
    </html>
    
  3. Save the page.

Now you can test the page in Design view to see how the control designers work.

To demonstrate the design-time rendering of the controls

  1. Switch to Design view for the page.

    The controls should appear as they do in the following screen shot. Notice that the second composite control is resizable, and the first is not.

    ControlDesigners.aspx page in Design view

    VS ControlDesigners.aspx in Design view graphic

  2. Click in the content region of the container control, and type some text content for the control.

  3. Switch to Source view, and locate the source code for the container control. Confirm that the text you typed in the region now appears in the source code.

  4. Switch back to Design view.

  5. Click the frame of the control, position the mouse pointer over one of the resizing icons, and resize the container control.

  6. Click in the editable region of the control at the end of the text content, and press ENTER to add a line break.

  7. Drag a Button control from the Toolbox and drop it into the editable region beneath the text you entered. Drag a Label control from the Toolbox and drop it next to the button. This demonstrates that you can drag child controls into the editable region. If you want, you can set properties on the child controls at design time, and you can add code for the Button control to update the Label control's Text property at run time.

    The page with the controls you just added should look similar to the following screen shot.

    Container control with child controls

    VS Container Control with child controls

  8. Save the page.

To view the page at run time

  • Load the page in a browser.

    The controls should appear as you customized them in Design view. Your page should look similar to the following screen shot.

    Completed control designers Web page

    VS Simple Control Designers Web Page

Next Steps

This walkthrough has demonstrated the basic tasks involved in creating a custom control associated with a composite or a container control designer. You created custom controls with designers that allowed you to resize the controls and add text in an editable region in the Design view in Visual Studio 2005. Suggestions for further exploration include:

See Also

Concepts

ASP.NET Control Designers Overview