In the very first article, I gave a few general trends and guidelines to follow. I also mentioned that I would give more of these when we touch on the appropriate subject... and here is the opportunity to give you some more guidelines and trends because we are at the appropiate subject:
Expose critical controls as protected properties (in the class level)
This is for any developer that may want to extend your composite control. This is to give developers that may want to extend your control a little bit further and they may need access to one of the controls in the composition. For example:
protected Image image = new Image();
protected Button button = new Button();
protected override void CreateChildControls() {
Controls.Add(image);
Controls.Add(button);
}
Ensure that you call the EnsureChildControls method at the critical point
I did not intend the pun at all. However, to this is to ensure that your CreateChildControls method is called once (provided that the EnsureChildControls method was used before). The EnsureChildControls method just checks if it has not called the CreateChildControls method before. If the ChildControlsCreated property is evaluated to false (when the EnsureChildControls method is called), it then calls the CreateChildControls method and sets the ChildControlsCreated property to true. Otherwise, the CreateChildControls method will not be executed.
It is best to call this as late as possible; but before the Render event of the page life cycle. It is also best to set default "values" on the controls that are being composed on the constructor of the server control containing the composition. Just before you have to do your processing, call the EnsureChildControls.
Do not render strings – compose controls
I have seen many control developers using strings to build the mark-up for their controls... and this is what essentially, composition is all about – removing the need for the output to be contained in repetive strings. Using other server controls in place is more ideal because those controls may be optimized to deliver “better” mark-up for specific browsers.
Besides that, it is a lot easier to work with objects (server controls in this case) than with raw strings; although, performance will be slightly slower (server controls vs. strings), it is a small price to pay for easier maintenance on the server control.
Who to inherit from for the composing control?
This has to do with the same discussion in the previous article Reusing and Creating Server Controls. The exact page where this was discussed was on page.
What if the composition gets a little bit too big for the controls to handle?
Sometimes, we all need an unique name to a control. Because of possible clashes with other sibling controls, you may implement the INamingContainer interface. This interface does not contain any members but advises ASP.NET to make a new naming namespace for the control and for all the child controls. Sometimes, it is necessary to implement this but not all the time it is needed.
Create interactive controls before rendering and display controls during rendering
If you want to create a control to render a “template” for the web browser, it would be best if the control is not added to the control tree at all. For example, you may just want to add a simple table output (and template it out as the following code):
protected override void Render(HtmlTextWriter writer) {
Table table = new Table();
table.Width = Unit.Percentage(85);
for (int j = 0; j < 3; j++) {
TableRow row = new TableRow();
for (int i = 0; i < 3; i++) {
TableCell cell = new TableCell();
cell.Text = String.Format("Row: {0}; Column: {1}",
j.ToString(), i.ToString());
row.Cells.Add(cell);
}
table.Rows.Add(row);
}
table.Rows[2].Cells[1].Text = "Something different";
writer.Write("<h3>Hello before the table.</h3>");
table.RenderControl(writer);
writer.Write("<h3>Hello after the table.</h3>");
}
However, if you need functionality (interaction) from the composition (the “templated” output), add the controls to the Control tree. The reason for this is for the control to become “alive” in the page life cycle, it has to exist in a "live" tree that "hooks" up with the page control tree. This will include interaction for the post-backs and data binding.
Note: I am using “templating the composition” and “templated composition” as loose terminology - please read the page titled "An Ending Note".