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

Create Composite Control using Ajax Toolkit Controls

4.67/5 (4 votes)
29 Nov 2008CPOL2 min read 38.7K   614  
How to create a Composite Control containing the features of Ajax ResizableControlExtender, CollapsiblePanelExtender and DragPanelExtender

Introduction

Ajax Control Toolkit allows the developer to create Web applications that can update data on the Web page without a complete reload of the page, and contain many controls with very interesting features: popup panels, resizable controls, floating controls and others.

Often you want a control with some features of some other controls, so you can achieve the goal of joining more controls in a single control as CompositeControl.
Composite Controls are controls that combine multiple controls together to form a new reusable control. For example, I want to create a control container that makes resizable, collapsible, draggable all guest controls as IFrame or others.
ResizableControlExtender, CollapsiblePanelextender, DragPanelExtender controls extend their own features to the Panel written on TargetControlID property so you can create a mix like this:

AjaxCompositePanel Control

AjaxCompositePanel Control

Background

This is a graphic representation of the control...

AjaxCompositePanel structure

... and this is the code, built in the page, of the control described in the bitmap above.

ASP.NET
<%--====== StyleSheet class needed by the control build in page ====--%>
...

<%-- PANEL CONTAINER --%>
<asp:Panel ID="PanelContainer" runat="server"  Visible="false" 
	style="Left:200px; Position:absolute; Top:100px;">
	<%-- PANEL CLOSE --%>
	<asp:Panel ID="PanelClose" runat="server" Height="20px">
		<asp:ImageButton ID="ImageButton1" 
		runat="server" style="cursor: hand"
		ImageAlign="Right" Height="100%" ImageUrl="~/images/close.gif"
		onclick="ImageButton1_Click" />
	</asp:Panel>

	<%-- PANEL HEADER --%>
	<asp:Panel ID="PanelHeader" runat="server" style="cursor: hand" Height="20px"
		BackImageUrl="~/images/RoundedGrayExplorer.gif">
	</asp:Panel>

	<%-- PANEL BODY --%>
	<asp:Panel ID="PanelBody" runat="server" BorderStyle="Solid" BorderWidth="1px">
		<iframe  id="ieframe" scrolling="auto" runat="server"
			src="HTMLPage.htm"
			height="100%"
			width="100%">
		</iframe >
	</asp:Panel>
</asp:Panel>

<%--====== AjaxPanelExtender Controls ============================--%>
...
<%--====== Client side script needed to the behavior ====--%>
...

Now we will convert it in a redistributable Composite Control.

Using the Code

In order to test the control build in the page, set AjaxCompositePanelBuildInPage.aspx as the project start page.
In order to test the composite control, set AjaxCompositePanelBuildInControl.aspx as the project start page.

Points of Interest

A composite control class AjaxCompositePanel inside AjaxCompositePanel.cs file inherits from the CompositeControl class, and has some class attributes...

C#
//This attribute gives to the control added on Visual Studio Toolbox 
//the icon of other control,View control in this case.
[ToolboxBitmap(typeof(View))]
//This attribute sets a control name displayed on the toolbox of Visual Studio.
[ToolboxData("<{0}:AjaxCompositePanel runat="server">")]
//This attribute sets a design-time rendering support class.
[Designer("AjaxCompositePanelControl.AjaxCompositePanelDesigner")]
public class AjaxCompositePanel : CompositeControl
{
    ...

... and some method attributes for design-time behaviors inside Visual Studio properties window:

C#
//Visible from Visual Studio properties windows.
[Browsable(true)]
//Property category
[Category("AjaxCompositePanel")]
//Property default value displayed on properties windows
[DefaultValue("")]
//Property description
[Description("Url of header image.")]
[Localizable(true)]
[RefreshProperties(RefreshProperties.Repaint)]
//Support to design time editors as select files URL or select color.
[UrlProperty]
[EditorAttribute(typeof(System.Web.UI.Design.ImageUrlEditor), 
	typeof(System.Drawing.Design.UITypeEditor))]
public string BarImageUrl
{
    ...

The main method of Custom Control is method named CreateChildControls which can be overridden, that calls CreateControlsHierarchy() within which a tree structure of the child control is built and added to the controls collection:

C#
protected virtual void CreateControlsHierarchy()
{
...
    //Create and set PanelContainer.
    Panel DragebleResizablePanelContainer = new Panel();
    DragebleResizablePanelContainer.ID = "DragebleResizablePanelContainer";
    DragebleResizablePanelContainer.Visible = false;
    DragebleResizablePanelContainer.Attributes["style"] = "float: right";

    //Create and set PanelHeader.
    Panel DrageblePanelHeader = new Panel();
    DrageblePanelHeader.ID = "DrageblePanelHeader";
    DrageblePanelHeader.Attributes["style"] = "cursor: hand";

    //Adds PanelHeader as child to the PanelContainer controls collection.
    DragebleResizablePanelContainer.Controls.Add(DrageblePanelHeader);

    //Adds PanelContainer to the controls collection of composite control.
    Controls.Add(DragebleResizablePanelContainer);
    ...

Composite Control client side behavior will need JavaScript methods that will be added to the page...

C#
//Adds a script block to the top of the page.
if (!Page.ClientScript.IsClientScriptBlockRegistered("clientScript"))
{
    System.Text.StringBuilder sb = new System.Text.StringBuilder();

    sb.Append("<script type="\"text/javascript\""></script>");
    Page.ClientScript.RegisterClientScriptBlock(this.GetType(), 
	"clientScript", sb.ToString(),false);
}
//Adds a script block into the page that executes when the page 
//finishes loading but before the page's onload event is raised.
if (!Page.ClientScript.IsStartupScriptRegistered("repositioningScript"))
{
    //Page.ClientScript.RegisterStartupScript(this.GetType(), 
    //"clientScript", sb.ToString(), false);
} 

... and also a stylesheet class used for Ajax Panel Extender will be added to the page:

C#
protected virtual void CreateControlsHierarchy()
{        ...
	//Adds to the page header a stylesheet class
    this.Page.Header.StyleSheet.CreateStyleRule(new ResizingIFrameCssClass(), 
	this.Page, ".resizingIFrame");
    ...
}
...

// Stylesheet class
class ResizingIFrameCssClass : Style
{
    protected override void FillStyleAttributes
	(CssStyleCollection attributes, IUrlResolutionService urlResolver)
    {
        base.FillStyleAttributes(attributes, urlResolver);
        attributes[HtmlTextWriterStyle.Padding] = "0px";
        attributes[HtmlTextWriterStyle.BorderStyle] = "solid";
        attributes[HtmlTextWriterStyle.BorderWidth] = "2px";
        attributes[HtmlTextWriterStyle.BorderColor] = "#B4D35D";
    }
}

At the end, only one word on Design-Time rendering of the control.
Inside AjaxCompositePanelDesigner.cs, you can see the AjaxCompositePanelDesigner class that inherits from the CompositeControlDesigner class, and GetDesignTimeHtml method which can be overridden that retrieves the HTML markup used to render the control at design time.

History

  • 28th November, 2008: Initial version

License

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