S
Sky
Hello:
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 (_ImageLocation == eAlign.Left){
oCell1.Controls.Add(oImg);oCell2.Controls.Add(new
LiteralControl(_HeaderText));
}else{
oCell2.Controls.Add(oImg);oCell1.Controls.Add(new
LiteralControl(_HeaderText));
}
//Good place to apply any custom styling too...
}
But NONE of the books seem to use the PreRender event -- in fact, it almost
looks like they steer away from it...Any reason why?
Finally -- one last dumb question. I see a lot of Examples/books/articles
stating that all get/set properties talking directly to a sub element should
have EnsureChildControls in front of it:
string Text {get {EnsureChildControls();return _TEXTBOX.Text;} set
{EnsureChildControls();_TEXTBOX.Text=value}}
Ok...maybe this is just me...but We're talking about using a function jump,
which checks a boolean property get function which covers a private
field...for EVERY public property that is set....Isn't this overkill????
Would it not be better to get this work out of the way as soon as possible,
once, and to not have to call EnsureChildControls() all the time?
How about doing it at the earliest possible time -- in the Constructor:
MyControl : WebControl{
//Constructor
MyControl():base(){
//Private Fields have been intialized already
//but no public properties have been called yet, so it's the right time
to do this:
EnsureChildControls();
}
......
}
My question: I get worried when I see that i am the only person doing
something ;-)....and I can't find a single person who is using
EnsureChildControls() in the constructor.... Is there any practical reason
that it is too early?
I know that I they won't be rehydrated yet, until the Page_Load(), but
that's ok. I just need to be able to get rid of EnsureChildControls() being
everywhere.
Thank you kindly for any advice you may have on how find the 'perfect'
recipie for building custom controls... ;-)
Sky
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 (_ImageLocation == eAlign.Left){
oCell1.Controls.Add(oImg);oCell2.Controls.Add(new
LiteralControl(_HeaderText));
}else{
oCell2.Controls.Add(oImg);oCell1.Controls.Add(new
LiteralControl(_HeaderText));
}
//Good place to apply any custom styling too...
}
But NONE of the books seem to use the PreRender event -- in fact, it almost
looks like they steer away from it...Any reason why?
Finally -- one last dumb question. I see a lot of Examples/books/articles
stating that all get/set properties talking directly to a sub element should
have EnsureChildControls in front of it:
string Text {get {EnsureChildControls();return _TEXTBOX.Text;} set
{EnsureChildControls();_TEXTBOX.Text=value}}
Ok...maybe this is just me...but We're talking about using a function jump,
which checks a boolean property get function which covers a private
field...for EVERY public property that is set....Isn't this overkill????
Would it not be better to get this work out of the way as soon as possible,
once, and to not have to call EnsureChildControls() all the time?
How about doing it at the earliest possible time -- in the Constructor:
MyControl : WebControl{
//Constructor
MyControl():base(){
//Private Fields have been intialized already
//but no public properties have been called yet, so it's the right time
to do this:
EnsureChildControls();
}
......
}
My question: I get worried when I see that i am the only person doing
something ;-)....and I can't find a single person who is using
EnsureChildControls() in the constructor.... Is there any practical reason
that it is too early?
I know that I they won't be rehydrated yet, until the Page_Load(), but
that's ok. I just need to be able to get rid of EnsureChildControls() being
everywhere.
Thank you kindly for any advice you may have on how find the 'perfect'
recipie for building custom controls... ;-)
Sky