ascx added at button click event doesn't carry the value on postback

B

Bob

I want to create an aspx page to load different ascx controls to create a
wizard like process, that is, the aspx page has a Continue button, on
initial load, it loads the first ascx control into a placeholder, on
postback, the page's button click event calls a public method on the ascx to
process data, then it removes this ascx, loads the second one, and so on.

Here's the pseudo code of the aspx:
void Page_Load(object sender, EventArgs e) {
if it's not postback - the first time
load ascx 1 into placeholder
else - subsequent postback
load ascx i into placeholder
(ascx i is ascx 1 on first postback, ascx 2 on second postback)

void Button_Click(object sender, EventArgs e) {
if it's the first postback
call ascx1.ProcessData()
remove ascx 1 from placeholder
add ascx 2 to placeholder.
else
call ascx2.ProcessData()

The problem is that the controls inside ascx 2 (e.g. textboxes) are all
empty at call ascx2.ProcessData() even if user entered data. I tracked this
down to the fact that ascx 2 is added to the placeholder in the Button_CLick
event, not in Page_load. This probably messes up its viewstate due to the
event sequence. However I still think my thinking of loading the ascx
controls one by one is a good conceptual design, and wonder if there is a
way to make this work.

Thanks
Bob
 
G

Guest

Hello Bob

I can't quite tell if this is relevant to your case, but I've been working on similar such stuff and one thing that's important: The (condensed) steps in building the page are 1) PageLoad, 2) Fire event handlers for buttons, grids, etc., and 3) PagePrerender.

In your case, on the first pass the page loads, you add your control, and the page renders. Now the user is looking at the page with your control and clicks a button. On the second pass, the page loads again, *then* the click event is processed. Is it possible that moving your PageLoad logic to PagePrerender would help

I don't totally understand all the ins and outs here, but hoping this might prod an idea. I also know that, as you say, the sequence of what's added when is very important to viewstate, and I'm just trying to figure it all out. You might consider at least for starters bypassing the automatic viewstate and using viewstate or session on your own to store things away and get them on your own terms. Shouldn't have to do this forever, but imho viewstate is a bit of a hairy beast to understand because there's so much going on behind the scenes, and sometimes it's better to do an end run at least for the moment

Finally, a user control is great for reusing logic, and if you need it on more than one page then that's the best way to go (although in that case the best way to communicate among them is by raising/consuming events, not by calling public methods). They're also handy if you want to customize them on disk without having to rebuild the app. But, in your case, I'm not sure that either of these is important to you. Anyway, have you considered this scenario: a single page, two panels with your two different sets of input, only one of which is visible at any one time? It's simpler and easier to code, and might do what you need

Bill Bor

----- Bob wrote: ----

I want to create an aspx page to load different ascx controls to create
wizard like process, that is, the aspx page has a Continue button, o
initial load, it loads the first ascx control into a placeholder, o
postback, the page's button click event calls a public method on the ascx t
process data, then it removes this ascx, loads the second one, and so on

Here's the pseudo code of the aspx
void Page_Load(object sender, EventArgs e)
if it's not postback - the first tim
load ascx 1 into placeholde
else - subsequent postbac
load ascx i into placeholde
(ascx i is ascx 1 on first postback, ascx 2 on second postback

void Button_Click(object sender, EventArgs e)
if it's the first postbac
call ascx1.ProcessData(
remove ascx 1 from placeholde
add ascx 2 to placeholder
els
call ascx2.ProcessData(

The problem is that the controls inside ascx 2 (e.g. textboxes) are al
empty at call ascx2.ProcessData() even if user entered data. I tracked thi
down to the fact that ascx 2 is added to the placeholder in the Button_CLic
event, not in Page_load. This probably messes up its viewstate due to th
event sequence. However I still think my thinking of loading the asc
controls one by one is a good conceptual design, and wonder if there is
way to make this work

Thank
Bo
 
B

Bob

Hi Bill, thanks for your reply and suggestions. I ended up doing something
similar to what you said at the end, loading both ascx into the aspx at the
same time but set the Visible property to true or false as appropriate. It
works fine for now but if the issues is expanded to have many ascx controls
in a multiple-step process, loading them all seems pretty heavy.

I just keep thinking there should be a way that the load-process-load next
design can work. It's such a no brainer in Windows app. I'll try some
different events like Prerender to see how it goes.

About your comments on doing event rather than public methods, do you mean
to add my own event in the ascx? What I'm doing right now is for the button
click event handler on the aspx to call the ascx public method. Do you mean
for it to fire a custom-made event in the ascx?

Thanks
Bob

Bill Borg said:
Hello Bob,

I can't quite tell if this is relevant to your case, but I've been working
on similar such stuff and one thing that's important: The (condensed) steps
in building the page are 1) PageLoad, 2) Fire event handlers for buttons,
grids, etc., and 3) PagePrerender.
In your case, on the first pass the page loads, you add your control, and
the page renders. Now the user is looking at the page with your control and
clicks a button. On the second pass, the page loads again, *then* the click
event is processed. Is it possible that moving your PageLoad logic to
PagePrerender would help?
I don't totally understand all the ins and outs here, but hoping this
might prod an idea. I also know that, as you say, the sequence of what's
added when is very important to viewstate, and I'm just trying to figure it
all out. You might consider at least for starters bypassing the automatic
viewstate and using viewstate or session on your own to store things away
and get them on your own terms. Shouldn't have to do this forever, but imho
viewstate is a bit of a hairy beast to understand because there's so much
going on behind the scenes, and sometimes it's better to do an end run at
least for the moment.
Finally, a user control is great for reusing logic, and if you need it on
more than one page then that's the best way to go (although in that case the
best way to communicate among them is by raising/consuming events, not by
calling public methods). They're also handy if you want to customize them
on disk without having to rebuild the app. But, in your case, I'm not sure
that either of these is important to you. Anyway, have you considered this
scenario: a single page, two panels with your two different sets of input,
only one of which is visible at any one time? It's simpler and easier to
code, and might do what you need.
 
G

Guest

Hi Bob

Yes, re events, someday you might consider raising a custom-made event from your user control. In your current case, there's no big advantage, because you've got a single page controlling that single control, and from what I gather there's no reason you'd ever create an instance of that control outside of that page. But consider a more complex scenario: you've got a number of user controls on a page, some of them nested within others. Presuming they need to react to each other in some way (i.e. you click on a product list control and you want the shopping cart to refresh), rather than having each of them have to know about and tell all the others what to do, you could raise events, and anybody who cared could listen. This is how Windows works: I'm a button, somebody clicked me so I call that out, and whether anybody is out there to listen is not my problem

Re what you were first trying to do, agreed that it should work. It's tough to tell without seeing code, but I'm hoping you'll find you're just missing something in the order of events--i.e. you're running some code in the page load that you really want to have happen *after* the button click has added the new control (in which case the code would go in prerender). It's also possible depending on how you've written this that your code trying to retrieve the values from the textboxes is not pointing to the instance of ascx2 you think it is

Finally, re viewstate, I read a great article by Peter van Ooijen that I think you'll find useful. To quote him

"The thing to watch when adding controls at run time is the moment in the page life cycle you do this. Adding a control can (but not always does) ruin the contents of the ViewState, so you should add the controls before the page starts "tracking" the ViewState. This is in the on_int event; the Page_Load is too late!

I presume "on_int" is OnInit. Anyway, the article's at dotnetjunkies.com; on the main page you'll see a link to recent articles and "User Controls and Other Useful Things". As an aside, at least for me reading everything this guy has written lately has been a big help in understanding a lot of what's happening under the covers

Regards

Bil

----- Bob wrote: ----

Hi Bill, thanks for your reply and suggestions. I ended up doing somethin
similar to what you said at the end, loading both ascx into the aspx at th
same time but set the Visible property to true or false as appropriate. I
works fine for now but if the issues is expanded to have many ascx control
in a multiple-step process, loading them all seems pretty heavy

I just keep thinking there should be a way that the load-process-load nex
design can work. It's such a no brainer in Windows app. I'll try som
different events like Prerender to see how it goes

About your comments on doing event rather than public methods, do you mea
to add my own event in the ascx? What I'm doing right now is for the butto
click event handler on the aspx to call the ascx public method. Do you mea
for it to fire a custom-made event in the ascx

Thank
Bo

Bill Borg said:
Hello Bob
on similar such stuff and one thing that's important: The (condensed) step
in building the page are 1) PageLoad, 2) Fire event handlers for buttons
grids, etc., and 3) PagePrerenderthe page renders. Now the user is looking at the page with your control an
clicks a button. On the second pass, the page loads again, *then* the clic
event is processed. Is it possible that moving your PageLoad logic t
PagePrerender would helpmight prod an idea. I also know that, as you say, the sequence of what'
added when is very important to viewstate, and I'm just trying to figure it
all out. You might consider at least for starters bypassing the automatic
viewstate and using viewstate or session on your own to store things away
and get them on your own terms. Shouldn't have to do this forever, but imho
viewstate is a bit of a hairy beast to understand because there's so much
going on behind the scenes, and sometimes it's better to do an end run at
least for the moment.more than one page then that's the best way to go (although in that case the
best way to communicate among them is by raising/consuming events, not by
calling public methods). They're also handy if you want to customize them
on disk without having to rebuild the app. But, in your case, I'm not sure
that either of these is important to you. Anyway, have you considered this
scenario: a single page, two panels with your two different sets of input,
only one of which is visible at any one time? It's simpler and easier to
code, and might do what you need.
 

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

Top