.NET Tutorials, Forums, Interview Questions And Answers
Welcome :Guest
 
Sign In
Register
 
Win Surprise Gifts!!!
Congratulations!!!


Top 5 Contributors of the Month
david stephan

Home >> Articles >> ASP.NET >> Post New Resource Bookmark and Share   

 Subscribe to Articles

Composite controls

Posted By:Manning       Posted Date: February 19, 2011    Points: 75    Category: ASP.NET    URL: http://www.dotnetspark.com  

Composite controls in asp.net. In this article the authors discuss how to how to build composite controls using ASP.NET.
 

This article is taken from the book ASP.NET 4.0 in Practice. The authors discuss how to how to build composite controls using ASP.NET..

 

Get 40% off any version of ASP.NET 4.0 in Practice with the checkout code dnspark40. Offer is only valid through www.manning.com.


Custom controls are often created by picking two or more controls and combining them to produce a single result. This aspect is important because you can reuse existing controls and add more features to simplify the use of common recurring situations.

Composite controls are treated separately because combining controls together is more challenging than
creating a new one from scratch. In this situation, specific problems may surface. For example, the controls need to be wrapped and their members exposed in the corresponding control. While this task is simple to perform, it is also time consuming. The reality is that you will map only the most used and useful members and add the others as needed. The problem with this class of controls is that you're hiding them from the outside, deciding what the external world may or may not use.

For this same reason, events handled internally by these controls can become your nightmare: in this scenario,
in fact, you need to implement an event bubbling technique (to let events propagate through the control tree) or define new events to expose the existing ones outside of the wrapped controls. In order to fully understand how these aspects will reflect on the creation of a composite control, our scenario will cover how to build composite controls using ASP.NET.


Problem

Suppose we need to create a special DropDownList that, in a single declaration, can be used to insert both the description and the options to be selected by the user. Using this control, we can save a lot in terms of markup to be written and we can reuse the same feature over and over in our projects.

Solution

Composite  controls  are  generally  created  by  deriving  from  CompositeControl  in System.Web.UI.WebControls. This class implements a lot of the logic necessary to apply custom controls that at the same time serve as Web Controls-they support styling, for example. If you do not need these features, you can opt for the simple Control class from System.Web.UI. This option will ensure that the generated markup
remains very simple, but you will need to manually add the missing features that CompositeControl already
provides.

Figure 1 shows the approach offered by composite controls.



Figure 1 A composite control combines more controls together. Externally, they are treated as a single control that encapsulates the entire logic.


In both cases, we will manipulate the Page's control tree and dynamically instantiate controls at runtime. Composite controls work by combining controls together, so the controls are added using the CreateChildControls method.
This method is called whenever a child control is needed, through a call to the EnsureChildControls
method. When manipulating the control tree, in fact, you need to be careful and remember that these are controls that will be nested into the control itself and then into the page. To add a control inside another, you have to
simply access its Controls properties and add it via the Add method, as explained in listing 1.

Listing 1 CreateChildControl will contain the nested controls declaration

C#

public class SuperDropDownList: CompositeControl, INamingContainer
{
protected override void CreateChildControls()
{
if (ChildControlsCreated)	#4 return;

Controls.Clear();	#1


Controls.Add(new LiteralControl("

")); Label labelText = new Label(); labelText.Text = Description; Controls.Add(labelText); #2 Controls.Add(new LiteralControl( string.IsNullOrEmpty(Description)?string.Empty: ": ")); DropDownList listControl = new DropDownList(); Controls.Add(listControl); #3 Controls.Add(new LiteralControl("

")); ChildControlsCreated = true; #4 } #5 }

VB

Public Class SuperDropDownList Inherits CompositeControl Implements INamingContainer
Protected Overrides Sub CreateChildControls()
If ChildControlsCreated Then	#4
Return
End If


Controls.Clear()	#1
Controls.Add(New LiteralControl("

")) Dim labelText As New Label() labelText.Text = Description Controls.Add(labelText) #2 Controls.Add(New LiteralControl(If(String.IsNullOrEmpty(Description), String.Empty, ": "))) Dim listControl As New DropDownList() Controls.Add(listControl) #3 Controls.Add(New LiteralControl("

")) ChildControlsCreated = True #4 End Sub #5 End Class

#1 Remove existing controls
#2 Add a new Label
#3 Add a new DropDownList
#4 Avoid control recreation


#5 The code continues after the text

As you can see in listing 1, we are adding some controls to display a DropDownList and a description. It is important to understand that, to remove unwanted controls from the control tree (such as Literal controls that may be added in markup), we are performing a call to Controls.Clear to reset the control tree. The code in #4 is not necessary because it already is included by CompositeControl; nevertheless, it is showing how to deal with this problem when another, simpler base control (like Control) is used. The results are shown in figure 2.



Figure 2 The new SuperDropDownList control is in action. It is combining different controls to provide a simple implementation.


The declaration of the properties is omitted from the previous listing for brevity. When we need to set the properties for the inner controls, a special approach must be used: we need to understand how to access an inner object's property from outside the control. In these situations, the most preferred way to go is the one contained in this snippet:

C#

public IList DataSource
{
get
{
EnsureChildControls();  #1 return ((DropDownList)Controls[3]).DataSource as IList;
}

set
{
EnsureChildControls(); ((DropDownList)Controls[3]).DataSource = value;
}
}

VB

Public Property DataSource() As IList
Get
EnsureChildControls()  #1
Return TryCast(DirectCast(Controls(3), DropDownList).DataSource, IList) End Get

Set
EnsureChildControls()
DirectCast(Controls(3), DropDownList).DataSource = value
End Set
End Property


#1 Will call CreateChildControls

As you can see, we are referring to the previously created control (in this case, the DropDownList) finding it by position and directly exposing its inner property. This is generally the best way to go because you do not have to keep the inner property in sync. (It is automatically performed using this pattern.)

HOW TO AVOID REFERENCING A CONTROL BY POSITION

In order to produce a cleaner code, you can also save a reference to the controls in CreateChildControls
and refer to them using this syntax, instead of finding them by position.


It is important to understand that the calls to EnsureChildControls are mandatory-this will ensure, in fact, that the controls are created before we access them. Now that the infrastructure of our control is in place, let's take a look at using events in composite controls.

Events in composite controls
Events are used in custom controls to simplify the code necessary to handle a state. A composite control hides the child controls, so you need to propagate their events outside of to the container by implementing an event wrapper.
Redirecting an event is a simple technique where the event is sent outside by intercepting it locally and then propagating it outside. It is easier to show you this snippet to help you understand how it works than spend many words describing it:

C#

public event EventHandler SelectedValueChanged;

protected void OnSelectedValueChanged(EventArgs e)
{
if (SelectedValueChanged != null) SelectedValueChanged(this, e);
}

VB

Public Event SelectedValueChanged As EventHandler

Protected Sub OnSelectedValueChanged(e As EventArgs) RaiseEvent SelectedValueChanged(Me, e)
End Sub

This snippet will expose a new event, called SelectedValueChanged, and a new OnSelectedValueChanged
method, used to define the event handler in the markup.

To make the event attached to the inner control, in the CreateChildControls method right after the
DropDownList instance, we add this simple code:

C#

DropDownList listControl = new DropDownList();
listControl.SelectedIndexChanged += (object sender, EventArgs e) => { OnSelectedValueChanged(e);
};

VB

Dim listControl as New DropDownList()
listControl.SelectedIndexChanged += Function(sender As Object, e As EventArgs) Do
OnSelectedValueChanged(e) 
End Function

This will ensure that, when the DropDownList's SelectedIndexChanged event is fired, our event will be too. The result is that the event handler created inside the Page will be called as well and our event will propagate outside the contained control.

Discussion

When building composite controls, you need to pay attention to the fact that you are not generating markup but composing your controls, mixing them together, and manipulating the Page's control tree.

While this is certainly easy to implement in a simple scenario like the one we chose here, because you are
leveraging existing controls, it may also be prone to error. As we've learned in this scenario, the point here is to understand how CreateChildControls and EnsureChildControls are working.

Summary

Building custom controls is often treated as an art. It is, in fact, one of the most challenging parts that you will find when dealing with ASP.NET. Starting with custom controls is not difficult, but advanced scenarios involve a very


deep mastering of ASP.NET. However, custom controls can help you to avoid code duplication, by implementing and supporting repetitive tasks.



ASP.NET 4.0 in Practice
EARLY ACCESS EDITION

Daniele  Bochicchio, Stefano  Mostarda, and  Marco  De
Sanctis
MEAP Began: February 2010
Softbound print: March 2011 (est.) | 425 pages
ISBN: 9781935182467


 Subscribe to Articles

     

Further Readings:

Responses

No response found. Be the first to respond this post

Post Comment

You must Sign In To post reply
Find More Articles on C#, ASP.Net, Vb.Net, SQL Server and more Here

Hall of Fame    Twitter   Terms of Service    Privacy Policy    Contact Us    Archives   Tell A Friend