Complex control lifecycle issue

I

Iain

I've built a control whose purpose is to render a shopping cart based on
templates and an Order object which gets passed to it.

I'm keeping the order object in the Session object and therefore have no
need to use ViewState for this control. Instead I create the ChildControls
based on what is in the Order (passed in during initialisation) and
databinding with the various templates in the page.

This seems to work fine (though there has been a certain amount of
frustration in the learning curve!).

What I want to do now is to add buttons into the templates which will cause
(say) an order line to be deleted. I want to take care of this in the
rendering control - I see no need to pass this up to the page it sits in.

So I've added the buttons into the template and caught the bubble as it
comes up. Then I make the changes (E.g. delete a line item) on the order
object.

This seemed to work the NEXT time I did something.

It turns out the issue (sorry about dribbling on here, but it is quite
complex!) is when things are made.

The CreateChildControls is called BEFORE the event handling / bubbling
happens. So in this instance I create my UI with the original order and
then modify the order to remove a line item. Of course the UI (in terms of
the control hierarchy) is already there so the removal has no effect until
the NEXT event.

I tried moving the creation of the control hierarchy (into render), but then
there were no controls to raise the event against.

Finally, I did both. I created the control hiearchy in CreateChildControls
and then deleted it and recreated it in Render.

This seems to work, but I can't help thinking, a) it's a horrid way to do
this and b) surely something will go wrong.

Can anyone suggest a better way of doing this (parsing the control tree to
remove the specific elements that are implicitly deleted is not really an
option. I don't think ... hmmm.)?

Or confirm that this is safe?

Thanks


Iain
 
V

Victor Garcia Aprea [MVP]

Hi Iain,

In a postback its okay to a) re-construct the previously created control
tree and then, after handling an event or so, b) re-create the control tree
to reflect the new changes before the control gets rendered. This may sounds
weird at first, but its a totally valid approach. a) is necessary in order
for state and events to work properly, then after an event has been fired
there is nothing wrong in maybe updating some of your control's properties
(let's say OrderLineCount) and recreate the children to reflect this change.

Just keep in mind that children should *always* be created in the
CreateChildControls method (never in Render as you may be suggesting in your
message).

Also, when you modify a property that should cause a recreation of child
controls make sure you add a call to base.ChildControlsCreated = false but
do not call CreateChildControls yourself, i.e.:

public int OrderLineCount {
set {
_orderLineCount = value;
// with the following you make sure a recreation of children (when
needed) using the new updated value
base.ChildControlsCreated = false;
}
}

Let me know if things look clear now,

--
Victor Garcia Aprea
Microsoft MVP | ASP.NET
Looking for insights on ASP.NET? Read my blog:
http://obies.com/vga/blog.aspx
 
I

Iain

Thanks Victor.

So, to summarise this approach makes sense but I should be careful of the
details.

Specifically, I should set

whenever I do something in an event that may affect the hierarchy.

What I wasn't clear on is when I should recreate the hierarchy?

Specifically, will the framework call CreateChildControls at an opportune
time automatically (before Render) or do I need to do a check at some point
(OnPreRender or Render?) and recreated them as needed?

Thanks again - sometimes you've done something 'right', but you can't quite
believe it!


Iain
 
V

Victor Garcia Aprea [MVP]

You don't need to explicity create the children, the framework will do that
automatically when they are needed, i.e. before rendering, or earlier if a
child need to load state or fire an event.

One situation you need to be aware of that the framework is not currently
covering is when you access a child by index, i.e:

[C#]
Control ctrl = Controls[3];

if when this code runs children were not yet created (because of any of the
previous considered reasons, i.e.: rendering,etc) then they WONT be
automatically created. So you're required to call base.EnsureChildControls
before accesing the Controls collection by index. A much better solution
would be to override the get accesor for the Controls property of your
composite control and call EnsureChildControls in there, i.e:

[C#]
public override ControlCollection Controls {
get {
base.EnsureChildControls ();
return base.Controls;
}
}

The next version of ASP.NET will include the scenario missing from the v1.x
bits by introducing a new CompositeControl base class that would do exactly
the same check in the Controls property get accesor as I described above.

Good luck with your custom control development!

--
Victor Garcia Aprea
Microsoft MVP | ASP.NET
Looking for insights on ASP.NET? Read my blog:
http://obies.com/vga/blog.aspx
 

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,754
Messages
2,569,528
Members
45,000
Latest member
MurrayKeync

Latest Threads

Top