8.3 Composite Controls


Many controls contain other controls as part of their definition ”these are termed composite controls. By embedding other controls within them, custom controls can be used to define " chunks " of forms that can potentially be reused from many different pages, complete with their own properties, events, and methods . Composite controls are built by creating child controls and adding them to the Controls collection of the parent control. All creation of child controls should take place in an override of the virtual function CreateChildControls . This function is inherited from the Control base class and is called at the correct time to create child controls (after the Load event, just before rendering).

8.3.1 Creating Child Controls

Listing 8-30 shows a simple composite control that implements a calculator by using three TextBox controls, a Button control, and some LiteralControl s intermingled. A LiteralControl is a simple control that renders its Text property and is especially useful when building composite controls for properly laying out the child controls. This control also shows an example of hooking up an event handler to a child control.

Listing 8-30 Composite Control Example
 public class CalcComposite : Control, INamingContainer {   TextBox _operand1;   TextBox _operand2;   TextBox _result;   private void OnCalculate(Object sender, EventArgs e)   {     int res = Convert.ToInt32(_operand1.Text) +               Convert.ToInt32(_operand2.Text);     _result.Text = res.ToString();   }   public int Result   { get { return Convert.ToInt32(_result.Text); }  }   protected override void CreateChildControls()   {     _operand1 = new TextBox();     _operand2 = new TextBox();     _result   = new TextBox();     Controls.Add(_operand1);     Controls.Add(new LiteralControl(" + "));     Controls.Add(_operand2);     Controls.Add(new LiteralControl(" = "));     Controls.Add(_result);     Controls.Add(new LiteralControl("<br/>"));     Button calculate = new Button();     calculate.Text = "Calculate";     calculate.Click += new EventHandler(this.OnCalculate);     Controls.Add(calculate);   } } 

Notice also that the control shown in Listing 8-30 implements the INamingContainer interface. This is a marker interface (one with no methods) that indicates to the containing page that this control has child controls that may need to be in a separate namespace. If there is more than one instance of a composite control on a given page, it is important that the child controls of each composite control not have ID clashes . Anytime you have child controls in a custom control, you should be sure to add support for INamingContainer to avoid ID clashes in the rendered HTML.

You may find that in your composite control, you would like to manipulate some of your child controls during the Load event of your control. The CreateChildControls method is not called until after the Load event has fired , however, so if you attempt to access any child controls within a Load handler, you will find none. To guarantee that your child controls have been created, you can always call EnsureChildControls() . This function checks to see if the CreateChildControls function has been called yet (by checking the ChildControlsCreated Boolean), and if not, calls it for you. For example, the composite control shown in Listing 8-31 explicitly calls EnsureChildControls from within its Load handler before it tries to set one of the children's values.

Listing 8-31 Calling EnsureChildControls
 public class CalcComposite : Control, INamingContainer {   TextBox _operand1;   TextBox _operand2;   TextBox _result;   protected void Page_Load(object src, EventArgs e)   {     EnsureChildControls();     _operand1.Text = "42";   }   protected override void CreateChildControls()   {     _operand1 = new TextBox();     _operand2 = new TextBox();     _result   = new TextBox();     //...   } } 

With a composite control, it may also be useful to retrieve a child control dynamically. This is easily done with the FindControl method, which takes the string identifier of the control and returns a reference to the control.

8.3.2 Custom Events

For a custom control to truly provide all the attributes of standard Web controls, it must be able to define and propagate events. You define events in a custom control by adding a public event data member of delegate type EventHandler . A client then attaches a method to the event handler, and it is up to the control to invoke that method whenever the event logically occurs. Listing 8-32 shows a modified version of our CalcComposite control with a custom event added. Note that it declares a public EventHandler member called MagicNumber to which clients can hook delegates. In our example, the EventHandler is invoked whenever the user calculates the value 42 with the calculator. Listing 8-33 shows a sample .aspx page that traps the MagicNumber event and populates a label in response.

Listing 8-32 Control with Custom Event Example
 public class CalcComposite : Control, INamingContainer {     // other members not shown   public event EventHandler MagicNumber; // public event   private void OnCalculate(Object sender, EventArgs e)   {     int res = Convert.ToInt32(_operand1.Text) +               Convert.ToInt32(_operand2.Text);     _result.Text = res.ToString();     if ((res == 42) && (MagicNumber != null))       MagicNumber(this, EventArgs.Empty); // Trigger event!   }   protected override void CreateChildControls()   {     // Other control creation not shown...     Button calculate = new Button();     calculate.Text = "Calculate";     calculate.Click += new EventHandler(this.OnCalculate);     this.Controls.Add(calculate);   } } 
Listing 8-33 Sample Custom Event Client
 <%@ Page Language="C#" %> <%@ Register TagPrefix="eadn"              Namespace="EssentialAspDotNet.CustomControls"              Assembly="CalcComposite" %> <html> <script language="C#" runat=server> private void MyCtrl_OnMagicNumber(Object src, EventArgs e) {   MagicNumberLabel.Text = "Magic number calculated!!"; } </script> <body>   <form runat=server>     <asp:Label id=MagicNumberLabel runat=server />     <eadn:SimpleComposite id="MyCtrl"        OnMagicNumber="MyCtrl_OnMagicNumber" runat=server />   </form> </body> </html> 


Essential ASP.NET With Examples in C#
Essential ASP.NET With Examples in C#
ISBN: 0201760401
EAN: 2147483647
Year: 2003
Pages: 94
Authors: Fritz Onion

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net