help: question about LifeCycle for controls that change the 'shape' of their control tree?

help: question about LifeCycle for controls that change the 'shape' of their control tree?

Post by Sky » Thu, 01 Jul 2004 21:10:47


ello:

All the books I have looked at about how to design custom composite server
controls talk about the LifeCycle..and although most is quite clear, there
is one nagging type of control creation that I am looking for clarification
about...Can anyone help?

The following example is a trivial one, but shows the point hopefully
clearly: It's a Table of two cells, that has an ImageLocation property which
determines if the layout should be flipped (image on left, text on right):

CustomHeader():WebControl{
//Protected Elements
HtmlRow ROW;
HtmlCell CELL1;
HtmlCell CELL2;
Label HEADER;
Image LOGO

//Private fields:
string _HeaderText;
string _ImgUrl;
eAlign _ImageLocation = eAlign.Right;

//Public Properties to access Private Fields:
string HeaderText {get {return _HeaderText;}set{_HeaderText;}}
//etc.....

//Constructor
CustomHeader():base{}

Init (){
EnsureCreateControls();
}

//LifeCycle
CreateChildControls {
oTable = new Table();
ROW = new TableRow();
oTable.Rows.Add(oRow);
CELL1 = new TableCell();
CELL2 = new TableCell2();

IMG = new Image();

if (_ImageLocation == eAlign.Left){
CELL1.Controls.Add(oImg);CELL2.Controls.Add(new
LiteralControl(_HeaderText));
}else{
CELL2.Controls.Add(oImg);CELL1.Controls.Add(new
LiteralControl(_HeaderText));
}
//etc...
}



With the above scenario, I have several questions:

a) This would work if the control is the public properties were set in the
IDE via HTML, because the Public 'Align' property would be set BEFORE the
CreateControls was called -- the page lifecyle would be
* Set Private Fields
* Constructor
* Set Public Properties from the HTML -- ie the Align
* Init
* CreateChildControls.

But this would fail if mucked around with via code, such as this on the page
that instantiates the controls
* MyControl oC = new MyControl();
* Page.Controls.Add(oC); //Triggers Init, OnLoad, and therefore
CreateChildControls...the shape is using the default align=left...
* oC.ImageLocation = eAlign.Right;
* Result: WRONG LAYOUT!!!! (Still Left instead of new Right).


The obvious answer I will probably get is ('don't set public properties once
added to the page')....But there are times when this is required...plus, I
don't see anywhere in the books where it was stated that Controls, once
added to the page, should not be touched. Seems to not be so 'dynamic' if
that is the case...

One way I've seen mentioned is to ...Rebuild everything...YIKES!:
Public eAlign ImageLocation {get {_ImageLocation;}set
{Controls.Clear()ChildControlsCreated=false; and re-EnsureChildControls().}}
This seems to be completly nutty...build a tree, to throw it away, and start
again...





So...
A work around seems to break the rendering into two parts: use the
CreateChildControls to create all the necessary components -- but not finish
the Tree until the PreRender stage:

CreateChildControls {
oTable = new Table();this.Controls.Add(oTable);
ROW = new TableRow();
oTable.Rows.Add(oRow);
CELL1 = new TableCell();
CELL2 = new TableCell2();

IMG = new Image();
//STOP HERE!!! NEXT PART IS DONE ONLY IN PAGE_PRERENDER LATER
}

Page_PreRender(){
if (_ImageLo