Maintaining state in programmatically created composite user controls

M

mark.norgate

Hi

I'm writing a timesheet application in ASP.NET (framework 1.1, VS 2003)
that includes a user control to manage project time allocation
(ProjectDetailsControl). This control is a composite control that
includes several DropDownList objects for project code, name and so on,
as well as TextBox objects for time allocation for each day. I had a
problem with this control not rendering when created programmatically,
but I've fixed that. Now I have another problem.

The control is not maintaining its view state, and I'm not sure how
best to implement it. On first entry to the page (and only the first
entry), the project data is loaded from a database and inserted into
the page's ViewState. The page then uses this view state information to
create the appropriate number of ProjectDetailsControl objects.

I thought I would populate the view state in the page and so, as an
experiment, I had something along the lines of:

ViewState["projectDetails_0_ProjectCodeDropDown"] =
projectReader["projectCode"]

This is the ID for the project code drop down generated by the
framework in the HTML. I thought that, since the drop down within my
ProjectDetailsControl is not picking up its state, I'd look in the
Page_Load of my ProjectDetailsControl to see what's actually in the
ViewState object.

Looking at the ViewState in the ProjectDetailsControl, I discovered
that it's actually empty, oddly, even though in the page it has lots of
stuff in it, including all the keys I'd put in myself.

Bit of a ramble...but bottom line is, how do I maintain state in
programmatically create composite user controls? I've had a look at
some articles, such as the Page Controller and Front Controller
patterns on the MSDN site, but they're not particularly illuminating in
terms of the actual nuts and bolts of maintaining state.

Cheers, Mark
 
C

CaffieneRush

Order matters.
1. Create the control(s).
2. Add the control(s) to parent's control collection.
3. Change control's properties - assuming these will be persisted in
viewstate. Or DataBind.

If you mix steps 2 and 3, your viewstate will not survive the postback.

Read the complete explanation by Scott Mitchell.
http://scottonwriting.net/sowblog/posts/2129.aspx
 
M

mark.norgate

Thanks a lot for the link.

I've looked at my code, and it is in fact following the order as
described in the article. I only bind to the database once, when
!IsPostBack, and the dropdown list is indeed maintaining its list of
values, and is maintaining the correct selection on each roundtrip.

The problem is setting the selected item in the dropdown on the first
entry to the page, when !IsPostBack. What I'm doing is adding all the
values of the child controls, such as the time allocation for each day,
and the selected item in the dropdowns, to the ViewState when
!IsPostBack; then, in my control's Page_Load, I'm trying to retrieve
these values from the ViewState to set the initial values of the
various controls when !IsPostBack.

Perhaps this is a crude way of doing it and violates the Page lifecycle
pattern. Perhaps I ought instead to set the initial values of the
controls in the Page and not worry about addressing the ViewState
directly. But it seems to me that the control itself should be looking
after the values of its children and the page shouldn't have to worry.
The only problem with that is that I'd need to know the key of the
value to put into the ViewState in the page so the controls can
retrieve it.

Does that make any sense? Sorry, I'm rambling. What are your thoughts?
There are a few ways it can be done, but I'm not sure what the best way
is. I don't really want my composite to start addressing the database
directly, I'd rather keep that on the page.

Mark
 
C

CaffieneRush

Let me see if I understand you correctly.

Within Page_Load check !IsPostBack
Save values of usercontrol to viewstate
Followed by
Retrieve values from viewstate and set various other controls with
these values.

I'd check and do one of the following:
1. As you suggested, set the initial values of the controls directly.
This has the added benefit of reducing viewstate bloat.

2. If you're programmatically adding your controls to your page
(perhaps to a panel or placeholder in the page)
then make sure you add all the controls to the page before saving and
retrieving values from viewstate.

3. Control's vewstate should be tracked automatically at the end of
your user control's init event.
The control's lifecycle starts when it is added to the page's control
tree if it added later like in Page_Load, it will hurry up it's own
lifecycle to match the page's lifecycle.
You can ensure that control's viewstate is tracked earlier in your
control's lifecycle by making a direct call to TrackViewState().
Previous to this (IsTrackingViewState = False) any modifications and
additions to the control's viewstate would not be saved.
 

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

Forum statistics

Threads
473,994
Messages
2,570,223
Members
46,812
Latest member
GracielaWa

Latest Threads

Top