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

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
 
R

Robert Koritnik

Your thinking is great but remember there is another property called
ChildControlsCreated, which you should set to true in your
CreateChildControls at the end. So consecutive calls to EnsureChildControls
won't actually rebuild the control tree.

EnsureChildControls is a method that just checks that control tree is
created. And it checks the above boolean property. So whenever you do
something on the control (set/get some property that should access any
control within the tree), you should call EnsureChildControls() method.

Actually when page is rendering it also calls EnsureChildControls
recursively on it's controls. So all controls are valid before rendering and
before the response is sent to the client all controls have a true value in
childcontrolscreated property.
 
S

Sky

Robert -- thanks for your response ;-)
Yes -- I did know about the EnsureChildControls() combo with the
ChildControls Created bool...
Which by the way seems to do more than just cover up a private bool -- I
noticed that if I CreateChildControls, and not set
ChildControlsCreatedExplicitly, and not call base.CreateChildControls(), the
ChildControlsCreated is set automatically (!!!). How, where, I don't know...
Maybe the code behind ChildControlsCreated looks something like

get { return (_ChildControlsCreated)||(this.Controls.Count>0);}

That aside, it still means that everytime EnsureChildControls is used in a
property get/set, one is adding a lot of jumping around and checking, for
something, that in my mind, should already have been taken care of... What i
mean is that the code that is happening is something like:

string MyProp(){
get {
EnsureChildControls();
//which does
* jump to addr of EnsureChildControls()
* if ((ChildControlsCreated)||this.Controls.Count>0)){return
true;}else{CreateChildControls();}
//back to your code:
//etc.
}
}
In other words -- its still atleast one addr jump, with all that the
Stack/Reflection stuff of C# does... -- a conditional, a possible iterator
creation, a count, then return...

Now, I know that I am really being a pain in the bum asking about a realy
small little waste of bytes -- but I am asking for the sake of getting a
good grip on the life-cycle -- because as far as I can tell , 3 books = 3
different understandings !.... It seems that there is a lot of confusion
out there about how to make a webcontrol be as flexible as a form control...
Or..which is what I suspect -- it's not the books, it's me who is
confused -- hence the questions ;-)


PS: What were your thoughts as to what I am doing about breaking up the
rendering into two parts (CreateChildControls/PreRender)? I'm working out
here alone at home and have little contact with other asp.net programmers,
so most of my methodology is home - brew...And sometimes, it gets so hard to
do something, that I start wondering if I am totally looking at the whole
thing from the wrong angle ....

Very best,
Sky
 
R

Robert Koritnik

About two step WebControl creation is a smart thing. Actually I had the same
thing in mind once. First you have to create those controls that will be in
question when ProcessViewState phase begins. That's what you wanted to do.
The second part in PreRender should position those already created controls
into new containers. Seem reasonable. I once tried to do the same thing, but
eventualy gave up, because I work in a multi developer environment and it
would probably confuse others that would be (maybe) reediting my custom
control.

there's also a great article on ViewState, which also covers some of the
very interesting part of the control's lifecycle:
http://msdn.microsoft.com/library/d...guide/html/cpconcontrolexecutionlifecycle.asp

The other thing about ChildControlsCreated is somewhere else I think. I also
saw, that EnsureChildControls gets executed even if you don't Create them
and set childcontrolscreated to true. To me it looked more like (not like
your get { checking two conditions}) checking the private bool and if false
calling ensureChildControls and thus making it true. Because I did something
like that. I created CreateChildControls, but I didn't call it in any method
or property set/get. But in the end my webcontrol got created WITH
CreateChildControls method. Looks like that a Page object before responding
back (probably just before SaveViewState) calls EnsureChildControls
recursively over all its containing controls.
 
S

Sky

Hi Robert -- and again, thanks for the feedback :) (When you work in a
vacuum like I, every feedback about how others are trying to solve things is
mana from heaven!)

A:
You said: "I once tried to do the same thing, but
eventualy gave up, because I work in a multi developer environment and it
would probably confuse others that would be (maybe) reediting my custom
control."

That was one of the reasons of asking the question...one of these days I
will have to take this skill and work with others, so I musn't stray too far
from the flock ;-)
The only question that remains of course was, after having considered this
approach, but having to work with others, WHAT methodology did you end up
working with as a solution to the two step process?

I agree that most controls don't change their layout -- and therefore making
the subcontrols, and placing them can be all done in
CreateChildControls() -- but I am still really confused as what to do about
Styles...-- I still see no good time to apply them! If I apply them at
CreateChildControls() it's too early and changes via code can happen later,
if I apply them in Render() too late, and PreRender() we both agree is a
good time -- but not to use it too often as it is not 'common practice' when
working in a team.
So when do YOU apply styles??? I saw the overrideable methods that are
specifically for applyStyles inline during the Render stage -- but that
looks more appropriate for controls that are made from scratch -- not
Composite Controls.

The question is also relevant of course because creating Designers for every
control is a very time consuming process -- the more often I can use a
GenericDesigner would be nice :) What are you guys doing? Designing custom
desginers for everything? Or not?

B:
As for CreateChildControls being called even if not called by code within a
custom control -- yes, I had noticed that...and thought that this was being
called by the page or someother control, as you suggested... But I think I
was very wary of it due to microsoft stating that it's time of being called
was indeterminant... ie could happen at any time. Hence my trying to get it
out of the way at a Determinant way, as early as possible....
(Addendum: on the page you mentioned it says: "The CreateChildControls
method is not listed in the table because it is called whenever the ASP.NET
page framework needs to create the controls tree and this method call is not
limited to a specific phase in a control's lifecycle. For example,
CreateChildControls can be invoked when loading a page, during data binding,
or during rendering."... )


C.
And to add another twist to the thread... talking about Designers. been
looking at trying to make an Editable webcontrol -- actually a collapsible
Expand/Collapse panel (aka XP panel) but be editable in the ide. For a
couple of nights I stumbled around trying to figure out what was wrong...and
finally found out about the ReadWriteDesigner... (or PanelDesigner)...but
was terribly disappointed that it doesn't contain a GenEditTimeHtml() (sorry
if I am not using the right names for the methods, but I don't have my ide
open, and have a terrible memory :) But I hope you know which method I am
referring to) and that its appearance in the ide is a plain IDE -- no
possiblity of making it an editable custom looking panel. Between the two
(a normal default ControlDesigner that can show the custom borders and
headers and icons, but not parse/make visible the contained controls till
run time), and a PanelEditor (which can show the contents but not the
border, etc until runtime)...I was wondering if I have overlooked something.
another designer? Another way? Any knowledge/advice on this?

D. And one last question. and totally off the original thread, but on my
mind a lot these days... As I said, I am developing this app in a vacuum
(stuck temporarily in France due to non-work issues -- with no
contemporaries to talk to in English) so have no idea how other shops are
working with ASP.NET...It seems to me that Server Controls compiled as Dll's
are...more time consuming, but a lot more reusable. Yet I think I see a lot
more ASCX/User Controls out there. What is your shop doing? Quick dev in
Ascx, then converting to server controls? What do you think most people are
doing? Over here in France, there is a huge drive/prefererance for non-US
controlled technologies...such as PHP...so most of the magazines are
focusing on that. What do you think is the flavour of the month in the US?
Is PHP growing due to people being thrown by the huge paradym shift that
ASP.NET is? Or is it gaining traction in small shops as well as big shops?
(I know that ASP.NET is already being used by huge firms -- but the everyday
webshop/small 10-20 person firms in the us are goind towards what?)
I know that whatever you may say is just an opinion, but frankly, any
opinion other than just my own these days, would be great ;-)


Very best,
Sky
 
S

Sky

(I posted this 2 days ago...but its only now that I see that somehow Outlook
didn't send it out? Anyway --second try)


Hi Robert -- and again, thanks for the feedback :) (When you work in a
vacuum like I, every feedback about how others are trying to solve things is
mana from heaven!)

A:
You said: "I once tried to do the same thing, but
eventualy gave up, because I work in a multi developer environment and it
would probably confuse others that would be (maybe) reediting my custom
control."

That was one of the reasons of asking the question...one of these days I
will have to take this skill and work with others, so I musn't stray too far
from the flock ;-)
The only question that remains of course was, after having considered this
approach, but having to work with others, WHAT methodology did you end up
working with as a solution to the two step process?
Is the obvious answer you have stopped fighting upstream and are using
EnsureChildControls() everywhere?


That said, I agree that most controls don't change their layout -- and
therefore making
the subcontrols, and placing them can be all done in
CreateChildControls() -- but I am still really confused as what to do about
Styles...-- I still see no good time to apply them! If I apply them at
CreateChildControls() it's too early and changes via code can happen later,
if I apply them in Render() too late, and PreRender() we both agree is a
good time -- but not to use it too often as it is not 'common practice' when
working in a team.
So when do YOU apply styles??? I saw the overrideable methods that are
specifically for applyStyles inline during the Render stage -- but that
looks more appropriate for controls that are made from scratch -- not
Composite Controls.

The question is also relevant of course because creating Designers for every
control is a very time consuming process -- the more often I can use a
GenericDesigner would be nice :) What are you guys doing? Designing custom
desginers for everything? Or not?

B:
As for CreateChildControls being called even if not called by code within a
custom control -- yes, I had noticed that...and thought that this was being
called by the page or someother control, as you suggested... But I think I
was very wary of it due to microsoft stating that it's time of being called
was indeterminant... ie could happen at any time. Hence my trying to get it
out of the way at a Determinant way, as early as possible....
(Addendum: on the page you mentioned it says: "The CreateChildControls
method is not listed in the table because it is called whenever the ASP.NET
page framework needs to create the controls tree and this method call is not
limited to a specific phase in a control's lifecycle. For example,
CreateChildControls can be invoked when loading a page, during data binding,
or during rendering."... )


C.
And to add another twist to the thread... talking about Designers. been
looking at trying to make an Editable webcontrol -- actually a collapsible
Expand/Collapse panel (aka XP panel) but be editable in the ide. For a
couple of nights I stumbled around trying to figure out what was wrong...and
finally found out about the ReadWriteDesigner... (or PanelDesigner)...but
was terribly disappointed that it doesn't contain a GenEditTimeHtml() (sorry
if I am not using the right names for the methods, but I don't have my ide
open, and have a terrible memory :) But I hope you know which method I am
referring to) and that its appearance in the ide is a plain looking white
box/panel -- no
possiblity of making it an editable custom looking panel with header and
footer. Between the two
(a normal default ControlDesigner that can show the custom borders and
headers and icons, but not parse/make visible the contained controls till
run time), and a PanelEditor (which can show the contents but not the
border, etc until runtime)...I was wondering if I have overlooked something.
another designer? Another way? Any knowledge/advice on this?
What about TemplateDesigner in such cases? Would this be a workaround? I
havn't used templates much so far, so don't know what to use them for/when
they are a better way to go. Are they sort of like a UserControl that
parsesrawhtml to make the childcontrols? Therefore we're talking about
slowing things down by adding parsing? Or?


D. And one last question. and totally off the original thread, but on my
mind a lot these days... As I said, I am developing this app in a vacuum
(stuck temporarily in France due to non-work issues -- with no
contemporaries to talk to in English) so have no idea how other shops are
working with ASP.NET...It seems to me that Server Controls compiled as Dll's
are...more time consuming, but a lot more reusable. Yet I think I see a lot
more ASCX/User Controls out there. Is that just because they are easier to
post
as articles, or because it is what most people are using/working with?
What is your shop doing? Quick dev in
Ascx, then converting to server controls? Staying with ascx? Not using
them?
What do you think most people are
doing? Over here in France, there is a huge drive/prefererance for non-US
controlled technologies...such as PHP...so most of the magazines are
focusing on that. What do you think is the flavour of the month in the US?
Is PHP growing due to people being thrown by the huge paradym shift that
ASP.NET is? Or is it gaining traction in small shops as well as big shops?
(I know that ASP.NET is already being used by huge firms -- but the everyday
webshop/small 10-20 person firms in the us are goind towards what?)
I know that whatever you may say is just an opinion, but frankly, any
opinion other than just my own these days, would be great ;-)


Very best,
Sky
 
R

Robert Koritnik

Ad.A
What methodology? Well the normal way. If som eproperty set changes child
controls, then you have to recreate the whole control... :( But manytimes
you can optimize things so code is still acceptable. I normally set style
while creating custom control. if that's in Create child controls or of it
is in Render. Whatever. I normally ALWAYS use CreateChildControls. Keeps me
thinking I have much more power over the creation. Code can get long, but
more understandable and more clean. And what is more important it actually
supports different client browsers while you use WebControls that support
this. If you use Render and actually write plain HTML, you have to take care
of that yourself.

Sometimes it's necessary that you create a designer. I once did that with a
templated databound custom control and still had some problems with
DataSource property. Whatever. But actually the designer pretty good
integrated into IDE so the control itself was perfectly editable with
different templates...
So if you intend to share this control and you know that others will use it
in Design mode then maybe you should create a designer to make it look more
end-resulting. But the problem here is with styles. You don't have the
HttpContext, so using images, and CSS from the web would be stupid. The only
thing to remember is to display in a manner that would give some information
to the developer-user.

Ad.B
Indeterminant tie of calling CreateChildControls. That's not tru all over.
Well .Net is perfectly deterministic, but the use of this method is
dependant on the custom control and it's behavior. YOu can call it whenever
you need to and as may times you need to. That's probably why they said is
not deterministic. Well all know when the constructor get's called or the
OnInit or OnLoad event, but for this method you actually don't exactly know
when, because it's not an event handler or anything like it...

Ad.C
You use Templates when there's a need to use them. Like templates for
different elements. That comes into mind especially with databound controls.

Ad.D
Decision between custom/user controls... Well. Custom controls are fast made
and less configurable (normally), Custom controls on te other hand are more
time consuming to develop but much much more reusable. If they are well
developed. Normally we really do make this decisions. We work on more
projects and whenever there's a need to produce a control that should be
reused (or has a tendence that it's so general that it will be reused)
accross projects we create custom controls. In all other cases we make user
controls. Sometimes applications use some specifics and that makes decisions
easyjer, because we know things will be harder to reuse. Right now we are
developing an app that extensiveli uses Microsoft UIPAB and some special
approaches and we know these controls are better used as tailored to this
framework than using some general custom controls because development would
be more time consuming and someone would have many more thing in mind
producing those...

Many small companies use non MS tools/technologies just because of cheaper
end product. MS means M$. But we are on MS products/platforms for so long
that we normally produce everything with MS products/technologies. An
myself? I was a while ago a Delphi "fan", but now since C# is out I don't
miss it all that much anymore. C# is a very good language and i actually
love ASP.Net. As much as I hated ASP, this one i really like. But I'm not
the one to judge this. Any grown-up and proved technology can be good. Then
it depends on your employer's strategy... Most of the times...
 
S

Sky

Dear Robert:
A. I think we are all on the same page. In other words, a little scoop of
CreateChildControls(), a dash of WebControls instead of HtmlControls, a
sprinkle of customDesigner/TypeConverters where needed. Fine. Seems I'm
going in the right direction ;-)

B. Poor choice of word on my part, but I think we both agree as to what it
does/when.

C....To be discussed in the future .... Templates are a thing/concept that I
havn't looked into at all -- concentrating on learning server controls right
now. Templates ...next week ;-)

D. Delphi was fun .So was C++Builder -- which kicked ass compared to VC++.
But happy those days are over. I still think OWL was the best framework --
even better (if less complete) than Net...but it's all so much better than 2
years ago with VB6 etc. I just wish that they had done as good a job with
ASP.NET as they did with the rest of the framework. It looks/feels half
baked...although I like very much where they are going with Framework 2
though (page events without having to do a secondary fetch -- all done
behind the page, I assume by XMLHttp requests?) Anyway.... But one thing I
Do NOT like is the speed at which I can produce. :-( WAY too heavy/intense
learning curve/special tricks/deep research for the most trivial things... I
can do a PHP website in a day -- it takes me a day to do one little control
in C#!!! Not right. They are expecting too much from webdesigners in my
opinion -- sort of trying to catapult webdesigners up to C++ levels... Too
steep....(Rant over -- back to work ;-)



Just wanted to say thanks for all your responses ;-)
Tonights new research/query in the forums is how to make a Custom
ControlBuilder to read nested/nested tags.... Maybe you know the answer to
that as well? :)

Very best,
Sky
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,901
Latest member
Noble71S45

Latest Threads

Top