5,448,416 members and growing! (19,198 online)
Email Password   helpLost your password?
Web Development » User Controls » General     Intermediate

Creating Custom User Control Designers in ASP.NET

By srirambalaji

An article on creating custom User Control designers in ASP.NET.
C#, VB.NET 1.1, Win2K, WinXP, Windows, .NET, ASP.NET, Visual Studio, VS.NET2003, Dev

Posted: 22 Mar 2005
Updated: 7 Apr 2005
Views: 73,945
Bookmarked: 44 times
Announcements
Want a new Job?



Search    
Advanced Search
Sitemap
14 votes for this Article.
Popularity: 4.18 Rating: 3.65 out of 5
4 votes, 28.6%
1
3 votes, 21.4%
2
1 vote, 7.1%
3
0 votes, 0.0%
4
6 votes, 42.9%
5

User Control Designer in Action

Introduction

A User Control is a server control that can be authored using declarative style as an ASP.NET web page. They provide web developers a quick way to create server controls.

User controls suffer from minimal design-time support in VS.NET. Their properties cannot be edited using Property Grid. This article is an attempt to create Custom Designers for User Controls which allow to edit their properties using Property Grid.

Header User Control

The code below shows a Header User Control which exposes Heading and SubHeading properties to allow the user to provide a heading and subheading for the page.

VB.NET

<%@ Control Language="vb" AutoEventWireup="false" 
        Codebehind= "Header.ascx.vb" Inherits="CustomDesignersWebVB.Header" %> 
<table align="center" ID= "tblHeader">
<tr>
    <td><asp:label id="lblHeading" Font-Size="18" Font-Name="Arial" 
          Font-Bold="True" Runat="server">Heading</asp:label></td>
</tr>
<tr>
    <td><asp:label id="lblSubHeading" Font-Size="14" Font-Name="Arial" 
          Font-Bold="True" Runat="server">Sub Heading</asp:label></td>
</tr>
</table>
Public Property Heading() As String
    Get
        Return lblHeading.Text
    End Get
    Set(ByVal Value As String)
        lblHeading.Text = Value
    End Set
End Property

Public Property SubHeading() As String
    Get
        Return lblSubHeading.Text
    End Get
    Set(ByVal Value As String)
        lblSubHeading.Text = Value
    End Set
End Property

C#

<%@ Control Language="C#" AutoEventWireup="false" 
      Codebehind= "Header.ascx.cs" Inherits="CustomDesignersWebCS.Header" %>
<table align="center" ID= "tblHeader">
<tr>
    <td><asp:label id="lblHeading" Font-Size="18" Font-Name="Arial" 
         Font-Bold="True" Runat="server">Heading</asp:label></td>
</tr>
<tr>
    <td><asp:label id="lblSubHeading" Font-Size="14" Font-Name="Arial" 
         Font-Bold="True" Runat="server">Sub Heading</asp:label></td>
</tr>
</table>
public string Heading
{
    get
    {
        return lblHeading.Text;
    }
    set
    {
        lblHeading.Text=value;
    }
}

public string SubHeading
{
    get
    {
        return lblSubHeading.Text;
    }
    set
    {
        lblSubHeading.Text=value;
    }
}

Creating a Custom Designer for Header User Control

Fire up Visual Studio .NET, use the File | New | Project menu item and select Web Control Library project template.

Add a Component Class to the project as shown below:

Creating the New Component Class

A Component Class is a class that inherits System.Component.Component. It can be added to the toolbox of VS.NET and can be dragged and dropped onto the design surface, and when selected, its properties are displayed using Property Grid.

Following is the code listing for the HeaderDesigner component class:

C#

private string _Heading ;
private string _SubHeading;

public string Heading
{
    get
    {
        return _Heading;
    }
    set
    {
        _Heading=value;
    }
}

public string SubHeading
{
    get
    {
        return _SubHeading;
    }
    set
    {
        _SubHeading=value;
    }
}

VB.NET

Private _Heading As String
Private _SubHeading As String

Public Property Heading() As String
        Get
            Return _Heading
        End Get
        Set(ByVal Value As String)
            _Heading = Value
        End Set
End Property

Public Property SubHeading() As String
    Get
        Return _SubHeading
    End Get
    Set(ByVal Value As String)
        _SubHeading = Value
    End Set
End Property

Header Designer exposes Heading and SubHeading properties to the user. The user sets these properties using a Property Grid.

Associating Designer with Header User Control

Open the project containing Header User Control. Add the HeaderDesigner component to the Components tab in the Toolbox, as shown below:

Adding HeaderDesigner to Toolbox

Drag and drop the HeaderDesigner to the design surface. Now you can set the Heading and SubHeading properties using the Property Grid as shown:

Setting Properties for UserControl

Open the code-behind for the page and add the following code:

C#

protected  Header Header1;
private void Page_Load(object sender, System.EventArgs e)
{
    //Glue code to associate the Usercontrol with the Designer

    if(!IsPostBack)
    {
      CustomDesignersCS.DesignerHelper.BindDesignerToControl(headerDesigner1, 
                                                                    Header1);
    }
}

VB.NET

Protected Header1 As Header

Private Sub Page_Load(ByVal sender As System.Object, _
             ByVal e As System.EventArgs) Handles MyBase.Load
    If Not Page.IsPostBack Then
      CustomDesignersVB.DesignerHelper.BindDesignerToControl(HeaderDesigner1, _
                                                                        Header1)
    End If
End Sub

BindDesignerToControl function is the glue code which binds HeaderDesigner properties to the user control properties. It uses Reflection to read Designer properties and associate them with the corresponding properties in the Header User Control.

C#

public class DesignerHelper
{
    public static void 
      BindDesignerToControl(System.ComponentModel.Component designer, Control ctl)
    {
        BindDesignerToObject(designer, ctl);
    }

    public static void 
      BindDesignerToObject(System.ComponentModel.Component designer, Object obj)
    {
        //Get object properties using Reflection

        PropertyDescriptorCollection colWebCtlPropDesc = 
                      TypeDescriptor.GetProperties(obj);

        //Get Designer properties using Reflection

        PropertyDescriptorCollection coldesignerPropDesc = 
                   TypeDescriptor.GetProperties(designer);

        //Loop through all Designer properties

        //Each designer property corresponds to webcontrol property

        foreach(PropertyDescriptor pd in coldesignerPropDesc)
        {
                PropertyDescriptor webctlpd = colWebCtlPropDesc.Find(pd.Name, true);

            if (webctlpd!=null)
            {
                //Assign the designer property value to web control's property

                webctlpd.SetValue(obj, pd.GetValue(designer));
            }

        }
    }
}

VB.NET

Public NotInheritable Class DesignerHelper _
    Public Shared Sub BindDesignerToControl(ByVal designer As _
    System.ComponentModel.Component, ByRef ctl As Control)
        BindDesignerToObject(designer, ctl)
    End Sub

    Public Shared Sub BindDesignerToObject(ByVal designer As _
           System.ComponentModel.Component, ByRef obj As Object)

        'Get object properties using Reflection

        Dim colWebCtlPropDesc As PropertyDescriptorCollection = _
                                 TypeDescriptor.GetProperties(obj)

        'Get Designer properties using Reflection

        Dim coldesignerPropDesc As PropertyDescriptorCollection = _
                              TypeDescriptor.GetProperties(designer)

        'Loop through Designer properties

        'Each designer property corresponds to webcontrol property

        For Each pd As PropertyDescriptor In coldesignerPropDesc
            Dim webctlpd As PropertyDescriptor = _
                           colWebCtlPropDesc.Find(pd.Name, True)

            If Not IsNothing(webctlpd) Then
                'Assign the designer property value to web control

                webctlpd.SetValue(obj, pd.GetValue(designer))
            End If
        Next
    End Sub
End Class

Points of Interest

While working on this article, I discovered that one can set the properties of BasePage class (custom Page class which all pages derive from) using the Property Grid in WebForms Designer.

Future enhancements and feedback

I am planning to do the following enhancements when time permits:

  • Creating a new property called "UserControl" in UserControlDesigner, which lists all the UserControls in the Page. User can pick the UserControl he wants to bind to the designer from the dropdown.
  • Creating a custom CodeDOMSerializer for the designer which automatically generates the binding code.

Feel free to email me your suggestions and comments. I would like to make improvements based on your feedback.

History

  • 3/21/05 - Version 1.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

srirambalaji


Sriram works as Senior Technical Specialist at Infosys's Microsoft Technology Center.

He has been working on ASP.NET,VB.NET,C#,ASP and SQL Server for past 7 years. He loves to churn out innovative ideas.

During his freetime,you may find him hiking, humming a song in his karaoke or listening to inspiring music. You can reach him at srirambalaji_work@yahoo.com.

Location: United States United States

Other popular User Controls articles:

Article Top
Sign Up to vote for this article
You must Sign In to use this message board.
FAQ FAQ Noise ToleranceSearch Search Messages 
 Layout  Per page   
 Msgs 1 to 10 of 10 (Total in Forum: 10) (Refresh)FirstPrevNext
Subject  Author Date 
QuestionInteresting Designermemberstixoffire9:55 2 May '08  
GeneralExtender Propertiesmember1:53 8 Jan '07  
GeneralThank you..memberme@vbman.com9:45 4 Apr '06  
GeneralRe: Thank you..membersrirambalaji23:55 18 Apr '06  
GeneralIExtendermemberKevin James20:19 28 Nov '05  
GeneralRe: IExtendermembersrirambalaji8:15 29 Nov '05  
GeneralMissing Class/Method DefinitionssussCodyT5:46 4 Apr '05  
GeneralRe: Missing Class/Method Definitionsmembersrirambalaji4:37 8 Apr '05  
GeneralReflectionsussgregec23:53 23 Mar '05  
GeneralRe: Reflectionmembersrirambalaji5:06 31 Mar '05  

General General    News News    Question Question    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

PermaLink | Privacy | Terms of Use
Last Updated: 7 Apr 2005
Editor: Smitha Vijayan
Copyright 2005 by srirambalaji
Everything else Copyright © CodeProject, 1999-2008
Web08 | Advertise on the Code Project