April 22, 2008
Posted on April 22, 2008
Composite Control Event in ASP.NET
This blog describes the different events that are relevant for rendering a composite control. It is very important to use these events correctly if you want the correct results. Even small mistakes in the use of the events can cause problems later on with events etc.
Writing a composite control is something most ASP.NET developers will do at some point. It isn’t a simple task if you do not know exactly how to do it. But following these basic rules will make your life much easier – and as a bonus, it will also make the reading of the code much easier for the people who will take over your work if you get hit by a car.
Composite controls must inherit Control and implement INamingContainer.
Constructor
The constructor is no different than usual. Set all values that define how the control is rendered here
OnInit
Create instances of controls that will be rendered on the page. If the controls has events that need to be captured, its necessary to create the events here. Otherwise the events will not be captured.
Also this is the place to set the static attributes of the controls.
Note that the controls are defined as protected attributes on the class and not just as local variables in the OnInit method. Also note that the controls are not added to the class’s control collection yet.
protected ImageButton _btnEdit;
protected override void OnInit( EventArgs e )
{
base.OnInit( e );
_btnEdit = new ImageButton();
_btnEdit.ImageUrl = “/UI/Images/edit.jpg”;
_btnEdit.Width = 46;
_btnEdit.Height = 18;
_btnEdit.Click += new ImageClickEventHandler( BtnEdit_Click );
_btnEdit.AlternateText = “Edit”;
….
….
}
CreateChildControls()
The CreateChildControls is used for adding the sub controls to the class control collection. And nothing else happens here. It is tempting to set attributes etc here, but you shouldn’t do that. If you want to build the entire output of controls, they all must be added here – and in the right order. But a good rule is to only add the controls that has interaction with the user. Not attributes for the rendering. Add buttons, text boxes, but do not add controls to render line breaks, images etc.
protected override void CreateChildControls( )
{
base.CreateChildControls();
this.Controls.Add( _btnEdit );
this.Controls.Add( _btnSend );
}
RenderControl
If you, like described above, only add controls that interact with the user, you need to override this method to render the control. The method makes it possible to render HTML around the controls you added in the CreateChildControls method. You can decide when to render the child controls. If you implement this in the Render method, the sub controls will be rendered when the base.Render is called. This means that they will be rendered before or after the HTML you would like to render. Using the RenderControl event, you can decide when the controls will be rendered and by that render them in the correct HTML context.
Always use the writer parameter to generate the HTML, because it implements some logic that will render correct HTML in different browsers.
public override void RenderControl( HtmlTextWriter writer )
{
base.RenderControl( writer );
// Render title html
writer.RenderBeginTag(HtmlTextWriterTag.H3);
writer.Write(“Top of buttons”);
writer.RenderEndTag();
writer.WriteLine();
_btnEdit.RenderControl( writer );
writer.RenderBeginTag(HtmlTextWriterTag.BR);
writer.RenderEndTag();
_btnSend.RenderControl( writer );
writer.RenderBeginTag(HtmlTextWriterTag.H3);
writer.Write(“End of buttons”);
writer.RenderEndTag();
}
Render
The render method should only be used if you do not wish to build the HTML through the RenderControl method. Using the Render method mean that you only generate HTML from the controls you have added to your control collection. Doing that will render the controls in the same order as they were added to the control collection.
It can still be very valuable to implement this method. It can be used to catch exceptions thrown by the rendering of one of the controls in the control collection.
protected override void Render( HtmlTextWriter writer )
{
try
{
base.Render( writer );
}
catch ( Exception ex )
{
string message = “Error while rendering a control”;
//Do logging etc.
}
}
Other events
There is a bunch of other events that can be necessary to implement to for instance control viewstate etc. These special events can be found in the event hierarchy below.
Event hierarchy:
Instantiate Constructor
Initialise OnInit method and Init event
Begin tracking view state TrackViewState method
(PostBack Only)
Load view state LoadViewState method
Load PostBack Data IPostBackDataHandler.LoadPostData method
Load OnLoad method and Load event
(PostBack only)
Raise Changed Events IPostBackDataHandler.RaisePostDataChangedEvent method
Raise PostBack Event IPostBackDataHandler.RaisePostBackEvent method
PreRender OnPreRender method and PreRender event
Save View State SaveViewState method
Render Render & RenderControls Method
Unload OnUnload method and Unload event
Dispose Dispose method