Groups | Blog | Home
all groups > asp.net webcontrols > june 2004 >

asp.net webcontrols : MultiPage Expert Please (Dynamic MultiPage controls)



Russ
6/29/2004 2:17:08 PM
I'm getting a little frazzled here. I have been trying to figure out
how to extract the data from my dynamically created Multipage controls
for about a week now!

Depending on data from a web service, I am adding one or more Tabs and
PageViews to a design time created TabStrip and MultiPage control.
Each PageView then gets a number of TextBoxes. Here is how I am
creating the controls:

for (int i=0; i < Ed.nRates; ++i)
{
// Ed is the data from the web service.
// Ed.Rd is an array of data, one element for each rate
CEmpRateData ERate = Ed.Rd [i];

if (i != 0)
{
TabSeparator ts = new TabSeparator ();
TabStrip1.Items.Add (ts);
}

Tab t = new Tab ();
t.Text = "Rate " + (ERate.m_Rate + 1);
TabStrip1.Items.Add (t);

PageView pv = new PageView ();
MultiPage1.Controls.Add (pv);

AddField (pv, "Regular Hours", 115,20, 40, 10);
AddField (pv, "Overtime Hours", 115,50, 40, 10);
.
.
.

Here's the AddField code:

private void AddField (PageView pv, String title, int x,
int y, int width, int lx)
{
Label Lb = new Label ();
Lb.Style.Add ("Position", "Absolute");
Lb.Style.Add ("Left", lx + "px");
Lb.Style.Add ("Top", y + "px");
Lb.Text = title + ":";
pv.Controls.Add (Lb);

TextBox box = new TextBox ();
box.Style.Add ("Position", "Absolute");
box.Style.Add ("Left", x + "px");
box.Style.Add ("Top", y + "px");
box.Style.Add ("Width", width + "px");
box.Text = "0";
pv.Controls.Add (box);
}

Now, this all works just fine as far as creating the pages and
textboxes and displaying them is concerned. The user can enter values
into the textboxes and switch to different tabs and then come back to
find the values are still there. The problem is in trying to submit
the entered values. When the user clicks the submit button, I need to
iterate through all of the created textboxes, extract their values and
send them to the web service for processing.

I thought I could do this by getting an IEnumerator from MultiPage1
and using it to get the PageViews, then getting an IEnumerator from
each PageView and using it to get each text box. But as soon as the
SubmitButton_Click fires, I look at MultiPage1.Controls in the
debugger and count is zero! It appears that all of the controls that
were created have already been disposed.

Originally this code was in a button load event, so the TabStrip and
MultiPage were being loaded with controls after the initial rendering
of the page. After much reading of this NG and studying, I thought I
understood that the problem was that dynamic creation had to take
place in the Page_Load routine and I was doing it too late. So I
rewrote the client to split the operation into two separate web forms,
one to select the data, and another to display it. That way I know at
page load time how many pages I need. But this did not help at all.
The MultiPage is still empty upon entering the submit routine.

Thanks very much for any help, Russ
Scott G.
6/29/2004 4:23:20 PM
There are a few things you need to keep in mind here; 1 The TabStrip =
will "recreate" itself via ViewState, so once the tabs are created they =
will automatically be recreated when you postback as long as you create =
the TabStrip(). 2 The MultiPage does NOT recreate itself, you have to =
create the controls on each MultiPage on each postpack.... 3. There's =
kind of "canonical" form for creating composite controls, that plays =
nicely with the framework; vary from the pattern and often frustrating =
things happen.

Do a google for "composite controls" and you'll get some idea of what =
that pattern is; here's how I would structure a control that does what =
you want (mix of real + psuedo code):

public class MultiTabCompositeControl : Control {
public override ControlCollection Controls {
get { this.EnsureChildControls(); }
}

TabStrip FormTabs;
MultiPage FormPages
protected override CreateChildControls() {
this.Controls.Clear();
FormTabs =3D new TabStrip(); // important that is created...
FormTabs.ID =3D "TS";
if (!IsPostBack) {
// don't create the individual tabs because ViewState is =
active
foreach tab=20
Tab t =3D new Tab();
FormTabs.Items.Add(t)
end
}
FormPages =3D new MultiPage();
FormPages.ID =3D "FP";
foreach multi page=20
PageView v =3D new PageView();
// add the controls to multipage this I would be a loop of =
the calls to create the labels/textboxes in you
FormPages.Controls.Add(v);
end
Controls.Add(FormTabs);
Controls.Add(FormPages);
FormTabs.TargetID =3D "FP";
this.ChildControlsCreated =3D true;
}
}

Now, if you give each of the TextBoxes you create an ID (which I think =
it always a good idea); you can iterate over the collection by either =
creating a search from the MultiTabCompositeControl -- or better yet, =
just keep track of the control objects as you create them in the =
CreateChildControls, and the access them in the even handler.

Good luck,
Scott


[quoted text, click to view]
I'm getting a little frazzled here. I have been trying to figure out
how to extract the data from my dynamically created Multipage controls
for about a week now! =20

Depending on data from a web service, I am adding one or more Tabs and
PageViews to a design time created TabStrip and MultiPage control.
Each PageView then gets a number of TextBoxes. Here is how I am
creating the controls:

for (int i=3D0; i < Ed.nRates; ++i)=20
{
// Ed is the data from the web service.
// Ed.Rd is an array of data, one element for each rate
CEmpRateData ERate =3D Ed.Rd [i];

if (i !=3D 0)=20
{
TabSeparator ts =3D new TabSeparator ();
TabStrip1.Items.Add (ts);
}

Tab t =3D new Tab ();
t.Text =3D "Rate " + (ERate.m_Rate + 1);
TabStrip1.Items.Add (t);

PageView pv =3D new PageView ();
MultiPage1.Controls.Add (pv);

AddField (pv, "Regular Hours", 115,20, 40, 10);
AddField (pv, "Overtime Hours", 115,50, 40, 10);
.
.
.

Here's the AddField code:

private void AddField (PageView pv, String title, int x,
int y, int width, int lx)
{
Label Lb =3D new Label ();
Lb.Style.Add ("Position", "Absolute");
Lb.Style.Add ("Left", lx + "px");
Lb.Style.Add ("Top", y + "px");
Lb.Text =3D title + ":";
pv.Controls.Add (Lb);

TextBox box =3D new TextBox ();
box.Style.Add ("Position", "Absolute");
box.Style.Add ("Left", x + "px");
box.Style.Add ("Top", y + "px");
box.Style.Add ("Width", width + "px");
box.Text =3D "0";
pv.Controls.Add (box);
}

Now, this all works just fine as far as creating the pages and
textboxes and displaying them is concerned. The user can enter values
into the textboxes and switch to different tabs and then come back to
find the values are still there. The problem is in trying to submit
the entered values. When the user clicks the submit button, I need to
iterate through all of the created textboxes, extract their values and
send them to the web service for processing.

I thought I could do this by getting an IEnumerator from MultiPage1
and using it to get the PageViews, then getting an IEnumerator from
each PageView and using it to get each text box. But as soon as the
SubmitButton_Click fires, I look at MultiPage1.Controls in the
debugger and count is zero! It appears that all of the controls that
were created have already been disposed.

Originally this code was in a button load event, so the TabStrip and
MultiPage were being loaded with controls after the initial rendering
of the page. After much reading of this NG and studying, I thought I
understood that the problem was that dynamic creation had to take
place in the Page_Load routine and I was doing it too late. So I
rewrote the client to split the operation into two separate web forms,
one to select the data, and another to display it. That way I know at
page load time how many pages I need. But this did not help at all.
The MultiPage is still empty upon entering the submit routine.

Scott G.
6/29/2004 4:30:23 PM

Oops; change Controls to

public override ControlCollection Controls {
get { this.EnsureChildControls(); return base.Controls(); }
}
[quoted text, click to view]
There are a few things you need to keep in mind here; 1 The TabStrip =
will "recreate" itself via ViewState, so once the tabs are created they =
will automatically be recreated when you postback as long as you create =
the TabStrip(). 2 The MultiPage does NOT recreate itself, you have to =
create the controls on each MultiPage on each postpack.... 3. There's =
kind of "canonical" form for creating composite controls, that plays =
nicely with the framework; vary from the pattern and often frustrating =
things happen.

Do a google for "composite controls" and you'll get some idea of what =
that pattern is; here's how I would structure a control that does what =
you want (mix of real + psuedo code):

public class MultiTabCompositeControl : Control {
public override ControlCollection Controls {
get { this.EnsureChildControls(); }
}

TabStrip FormTabs;
MultiPage FormPages
protected override CreateChildControls() {
this.Controls.Clear();
FormTabs =3D new TabStrip(); // important that is created...
FormTabs.ID =3D "TS";
if (!IsPostBack) {
// don't create the individual tabs because ViewState is =
active
foreach tab=20
Tab t =3D new Tab();
FormTabs.Items.Add(t)
end
}
FormPages =3D new MultiPage();
FormPages.ID =3D "FP";
foreach multi page=20
PageView v =3D new PageView();
// add the controls to multipage this I would be a loop of =
the calls to create the labels/textboxes in you
FormPages.Controls.Add(v);
end
Controls.Add(FormTabs);
Controls.Add(FormPages);
FormTabs.TargetID =3D "FP";
this.ChildControlsCreated =3D true;
}
}

Now, if you give each of the TextBoxes you create an ID (which I think =
it always a good idea); you can iterate over the collection by either =
creating a search from the MultiTabCompositeControl -- or better yet, =
just keep track of the control objects as you create them in the =
CreateChildControls, and the access them in the even handler.

Good luck,
Scott


[quoted text, click to view]
I'm getting a little frazzled here. I have been trying to figure =
out
how to extract the data from my dynamically created Multipage =
controls
for about a week now! =20

Depending on data from a web service, I am adding one or more Tabs =
and
PageViews to a design time created TabStrip and MultiPage control.
Each PageView then gets a number of TextBoxes. Here is how I am
creating the controls:

for (int i=3D0; i < Ed.nRates; ++i)=20
{
// Ed is the data from the web service.
// Ed.Rd is an array of data, one element for each rate
CEmpRateData ERate =3D Ed.Rd [i];

if (i !=3D 0)=20
{
TabSeparator ts =3D new TabSeparator ();
TabStrip1.Items.Add (ts);
}

Tab t =3D new Tab ();
t.Text =3D "Rate " + (ERate.m_Rate + 1);
TabStrip1.Items.Add (t);

PageView pv =3D new PageView ();
MultiPage1.Controls.Add (pv);

AddField (pv, "Regular Hours", 115,20, 40, 10);
AddField (pv, "Overtime Hours", 115,50, 40, 10);
.
.
.

Here's the AddField code:

private void AddField (PageView pv, String title, int x,
int y, int width, int lx)
{
Label Lb =3D new Label ();
Lb.Style.Add ("Position", "Absolute");
Lb.Style.Add ("Left", lx + "px");
Lb.Style.Add ("Top", y + "px");
Lb.Text =3D title + ":";
pv.Controls.Add (Lb);

TextBox box =3D new TextBox ();
box.Style.Add ("Position", "Absolute");
box.Style.Add ("Left", x + "px");
box.Style.Add ("Top", y + "px");
box.Style.Add ("Width", width + "px");
box.Text =3D "0";
pv.Controls.Add (box);
}

Now, this all works just fine as far as creating the pages and
textboxes and displaying them is concerned. The user can enter =
values
into the textboxes and switch to different tabs and then come back =
to
find the values are still there. The problem is in trying to submit
the entered values. When the user clicks the submit button, I need =
to
iterate through all of the created textboxes, extract their values =
and
send them to the web service for processing.

I thought I could do this by getting an IEnumerator from MultiPage1
and using it to get the PageViews, then getting an IEnumerator from
each PageView and using it to get each text box. But as soon as the
SubmitButton_Click fires, I look at MultiPage1.Controls in the
debugger and count is zero! It appears that all of the controls =
that
were created have already been disposed.

Originally this code was in a button load event, so the TabStrip and
MultiPage were being loaded with controls after the initial =
rendering
of the page. After much reading of this NG and studying, I thought =
I
understood that the problem was that dynamic creation had to take
place in the Page_Load routine and I was doing it too late. So I
rewrote the client to split the operation into two separate web =
forms,
one to select the data, and another to display it. That way I know =
at
page load time how many pages I need. But this did not help at all.
The MultiPage is still empty upon entering the submit routine.

Russ
6/29/2004 8:02:34 PM
Scott, thanks very much for the prompt response. Did I mention that I
am new to about all aspects of this? I guess not but maybe it was
obvious by my question. Anyway I'm not sure I understand what
postback has to do with it. Earlier I tried to find a definition of
'postback' and failed, everything I could find seemed circular:
"Postback is when the client posts back".

But I think that postback is when the web page is recreated after
passing control to the client and the client puts the same page up
again. If that is correct, then I am not doing a postback because
immediately after the submit operation is completed I am doing a
Server.Transfer to a different web page. In other words I am not
expecting the page to be recreated at all.

So, I have to conclude that postback means more than I think it does,
or else people are using it to mean more than it does. Either way, I
will research what you have sent me and see if I can learn to make it
work.

Thanks again, Russ

On Tue, 29 Jun 2004 16:30:23 -0400, "Scott G."
[quoted text, click to view]
Scott G.
6/30/2004 4:48:52 PM

A postback is kind-a the same as "Submit" (in the simple old world of =
CGI). The first time a page is generated is "not posted back"; after =
that the controls on the page (buttons + other javascript events) all do =
a "postback" (i.e. postback comes from the HTTP POST). I'm simplifying =
here....

In your example, you said the page was generated, but when a =
"SubmitButton_Click" event happens the page was missing the controls -- =
the "SubmitButton_Click" is the result of a postback --- thus, to =
actually get at the controls in the SubmitButton_Click you have to =
recreate the controls (and in my code I posted the CreateChildControls =
is called during the postback and the controls will be populated with =
the "data" from the user).

Scott

[quoted text, click to view]
Scott, thanks very much for the prompt response. Did I mention that I
am new to about all aspects of this? I guess not but maybe it was
obvious by my question. Anyway I'm not sure I understand what
postback has to do with it. Earlier I tried to find a definition of
'postback' and failed, everything I could find seemed circular:
"Postback is when the client posts back".

But I think that postback is when the web page is recreated after
passing control to the client and the client puts the same page up
again. If that is correct, then I am not doing a postback because
immediately after the submit operation is completed I am doing a
Server.Transfer to a different web page. In other words I am not
expecting the page to be recreated at all.

So, I have to conclude that postback means more than I think it does,
or else people are using it to mean more than it does. Either way, I
will research what you have sent me and see if I can learn to make it
work.

Thanks again, Russ

On Tue, 29 Jun 2004 16:30:23 -0400, "Scott G."
[quoted text, click to view]
Russ
6/30/2004 6:27:12 PM
Hi again Scott. Ok, I have tried what you suggested as well as I can
comprehend and have failed again. The new control class appears to do
nothing - not even display. I created a composite control class along
the lines you suggested, after doing the reading you suggested. Then
I created an instance of the new class, setting it's data members to
contain the information needed to create all the pages and controls.

When it did not work, I tried placing a breakpoint in the
CreateChildControls routine, and it never gets there. When is that
routine supposed to be called?

Below is the code I used, with some settings omitted for brevity. (I
didn't assign any id's to the TextBoxes yet because I just want to see
it display properly before starting to worry about getting the data
out.)

Thanks for any additional help you can provide.

Russ

In my class definition:

MultiTabCompositeControl TabCtrl;


In Page_Load (not within IsPostBack):

TabCtrl = new MultiTabCompositeControl ();
TabCtrl.nRates = (int) Ed.nRates;
TabCtrl.Er = Ed.Rd; // The array of rate data

// The composite class
public class MultiTabCompositeControl : Control, INamingContainer
{
public override ControlCollection Controls
{
get { this.EnsureChildControls(); return base.Controls; }
}

public int nRates; // number of pages needed
public CEmpRateData [] Er;

TabStrip FormTabs;
MultiPage FormPages;

protected override void CreateChildControls ()
{
this.Controls.Clear ();
FormTabs = new TabStrip (); // important that is
created...
FormTabs.ID = "TS";
FormTabs.Style.Add ("POSITION", "absolute");
FormTabs.Style.Add ("LEFT", "10px");
FormTabs.Style.Add ("TOP", "280px");
.
.

FormPages = new MultiPage ();
FormPages.ID = "FP";
FormPages.Style.Add ("POSITION", "absolute");
FormPages.Style.Add ("LEFT", "10px");
.
.

for (int i=0; i < nRates; ++i) {
CEmpRateData ERate = Er [i];

if (! Page.IsPostBack) { // don't create the tabs
// if ViewState is active
Tab t = new Tab ();
t.Text = "Rate " + (ERate.m_Rate + 1);
FormTabs.Items.Add (t);
}

PageView pv = new PageView ();
FormPages.Controls.Add (pv);

AddField (pv, "Regular Hours", 115,20, 40, 10);
AddField (pv, "Overtime Hours", 115,50, 40, 10);
.
.

}
Controls.Add (FormTabs);
Controls.Add (FormPages);
FormTabs.TargetID = "FP";
this.ChildControlsCreated = true;
}

private void AddField (PageView pv, String title,
int x, int y, int width, int lx)
{
Label Lb = new Label ();
Lb.Style.Add ("Position", "Absolute");
Lb.Style.Add ("Left", lx + "px");
Lb.Style.Add ("Top", y + "px");
Lb.Text = title + ":";
pv.Controls.Add (Lb);

TextBox box = new TextBox ();
box.Style.Add ("Position", "Absolute");
box.Style.Add ("Left", x + "px");
box.Style.Add ("Top", y + "px");
box.Style.Add ("Width", width +"px");
box.Text = "0";
pv.Controls.Add (box);
}
}

Russ
6/30/2004 8:08:17 PM
Ahh, I see. I figured there was more to it than I was thinking about.
Now if I could only get it to work. (See my last posting for details
of current try).

Thanks, Russ

On Wed, 30 Jun 2004 16:48:52 -0400, "Scott G."
[quoted text, click to view]
Scott G.
6/30/2004 10:09:31 PM
Here's my attempt (does kind of what you are doing); look at the trace =
and you'll see the posted back values when you click on the "Button". =
Note there are a lot of ways to handle the TextBoxes, in my example I'm =
just searching for them, but you could do something else (probably =
better).

To answer your question about when does CreateChildControls get called, =
it gets called when the control tree calls the Controls property. In the =
initial case this is likely to happen in PreRender when the framework =
asks for all of the Controls for a control and asks to render each =
control; later on when doing event handling etc.

Scott


<%@ Page language=3D"c#" AutoEventWireup=3D"false" Trace=3D"true" %>
<%@ Import Namespace=3D"Microsoft.Web.UI.WebControls" %>
<html>
<head>
<script language=3D"C#" runat=3D"server">
MultiTabCompositeControl tab;
protected override void OnInit(EventArgs e)
{
tab =3D new MultiTabCompositeControl();
this.PlaceHolder1.Controls.Add(tab);
}
=20
public void Button1_Click(object sender, System.EventArgs e) {
tab.TraceTextBoxes();
}
=20
public class MultiTabCompositeControl : System.Web.UI.Control, =
INamingContainer {
public ControlCollection Controls {
get {
this.EnsureChildControls();
return base.Controls;
}
}
=20
TabStrip FormTabs;
MultiPage FormPages;
=20
TextBox tb0;
TextBox tb1;
protected override void CreateChildControls() {
this.Controls.Clear();
=20
FormTabs =3D new TabStrip();
FormTabs.ID =3D "TS";
Controls.Add(FormTabs);
=20
if (!this.Page.IsPostBack)
{
Tab t =3D new Tab();
t.Text =3D "One";
FormTabs.Items.Add(t);
=20
t =3D new Tab();
t.Text =3D "Two";
FormTabs.Items.Add(t);
}
=20
FormPages =3D new MultiPage();
FormPages.ID =3D "MP";
for (int i =3D 0; i < 2; i++)
{
PageView pv =3D new PageView();
Label l =3D new Label();
l.ID =3D "LB" + i;
l.Text =3D "Label " + i;
pv.Controls.Add(l);
TextBox tb =3D new TextBox();
if (i =3D=3D 0) tb0 =3D tb; else tb1 =3D tb;
tb.ID =3D "TB" + i;
pv.Controls.Add(tb);
FormPages.Controls.Add(pv);
}
=20
FormTabs.TargetID =3D "MP";
=20
Controls.Add(FormPages);
=20
this.ChildControlsCreated =3D true;
}
=20
public void TraceTextBoxes() {
TextBox tb =3D LocateControl(this, "TB0") as TextBox;
if (tb !=3D null) {
this.Page.Trace.Warn("TB0 =3D " + tb.Text);
}
tb =3D LocateControl(this, "TB1") as TextBox;
if (tb !=3D null) {
this.Page.Trace.Warn("TB1 =3D " + tb.Text);
}
}
=20
private static System.Web.UI.Control =
LocateControl(System.Web.UI.Control root, string name) {
if (root =3D=3D null || name =3D=3D null) {
return null;
}
foreach (System.Web.UI.Control c in root.Controls) {
if (c.ID !=3D null && c.ID.EndsWith(name)) {
return c;
}
if (c.Controls.Count > 0) {
System.Web.UI.Control t =3D LocateControl(c, name);
if ( t !=3D null ) {
return t;
}
}
}
return null;
}
}
</script>
<meta http-equiv=3D"Content-Type" content=3D"text/html; =
charset=3Dutf-8">
<meta name=3D"GENERATOR" content=3D"Microsoft Visual Studio 7.0">
<meta name=3D"CODE_LANGUAGE" content=3D"C#">
<meta name=3D"vs_defaultClientScript" content=3D"JavaScript">
<meta name=3D"vs_targetSchema" =
content=3D"http://schemas.microsoft.com/intellisense/ie5">
</head>
<body>
<form id=3D"Form1" method=3D"post" runat=3D"server">
<p>
<asp:placeholder id=3D"PlaceHolder1" =
runat=3D"server"></asp:placeholder></p>
<p>
<asp:button id=3D"Button1" runat=3D"server" text=3D"Button" =
onclick=3D"Button1_Click"></asp:button></p>
</form>
</body>
</html>


[quoted text, click to view]
Hi again Scott. Ok, I have tried what you suggested as well as I can
comprehend and have failed again. The new control class appears to do
nothing - not even display. I created a composite control class along
the lines you suggested, after doing the reading you suggested. Then
I created an instance of the new class, setting it's data members to
contain the information needed to create all the pages and controls.

When it did not work, I tried placing a breakpoint in the
CreateChildControls routine, and it never gets there. When is that
routine supposed to be called?

Below is the code I used, with some settings omitted for brevity. (I
didn't assign any id's to the TextBoxes yet because I just want to see
it display properly before starting to worry about getting the data
out.)

Thanks for any additional help you can provide.

Russ

In my class definition:

MultiTabCompositeControl TabCtrl;


In Page_Load (not within IsPostBack):

TabCtrl =3D new MultiTabCompositeControl ();
TabCtrl.nRates =3D (int) Ed.nRates;
TabCtrl.Er =3D Ed.Rd; // The array of rate data

// The composite class
public class MultiTabCompositeControl : Control, INamingContainer=20
{
public override ControlCollection Controls=20
{
get { this.EnsureChildControls(); return base.Controls; }
}

public int nRates; // number of pages needed
public CEmpRateData [] Er;

TabStrip FormTabs;
MultiPage FormPages;

protected override void CreateChildControls ()=20
{
this.Controls.Clear ();
FormTabs =3D new TabStrip (); // important that is
created...
FormTabs.ID =3D "TS";
FormTabs.Style.Add ("POSITION", "absolute");
FormTabs.Style.Add ("LEFT", "10px");
FormTabs.Style.Add ("TOP", "280px");
.
.

FormPages =3D new MultiPage ();
FormPages.ID =3D "FP";
FormPages.Style.Add ("POSITION", "absolute");
FormPages.Style.Add ("LEFT", "10px");
.
.

for (int i=3D0; i < nRates; ++i) {
CEmpRateData ERate =3D Er [i];

if (! Page.IsPostBack) { // don't create the tabs
// if ViewState is active
Tab t =3D new Tab ();
t.Text =3D "Rate " + (ERate.m_Rate + 1);
FormTabs.Items.Add (t);
}

PageView pv =3D new PageView ();
FormPages.Controls.Add (pv);

AddField (pv, "Regular Hours", 115,20, 40, 10);
AddField (pv, "Overtime Hours", 115,50, 40, 10);
.
.

}
Controls.Add (FormTabs);
Russ
7/1/2004 4:57:34 PM
Ok Scott. I've got it working:) Part of my problem was the transition
from regular windows programming to web programming. I have now
deduced that I cannot create controls in the code behind and have them
appear in the browser - I have to declare them in HTML. I thought the
system would automatically generate the HTML for me if they were
instantiated in code.

So, I removed: TabCtrl = new MultiTabCompositeControl (), from my code
and added the following to my aspx file:

<%@ Register TagPrefix="mtcc" Namespace="MultiTabCompositeControls"
Assembly="PayrollEntryClient" %>

and in the Form:

<mtcc:MultiTabCompositeControl id="TabCtrl1"
runat="server"></mtcc:MultiTabCompositeControl>

(All Styles and other settings are done in code).

This now starts to work. The tabs and pages come up and display just
the same as they did before. And when the submit event fires, the
CreateChildControls() routine is executed first. However there were
still problems. I saw three significant differences between what you
last showed and what I am doing/need.

1. Your code is all in script while mine is all in code-behind. I am
don't think this makes any difference..

2. Your example does not depend upon any values external to the
composite control class in order to generate the internal controls.

3. You are not pre-setting the text boxes to zero like I do. I am
setting the initial values in the create routines, so when they are
re-created they would all be zero again.

With regard to #2, I am handling the external values by loading them
into the composite control class variables at page load time. But the
problem was that when CreateChildControls() is called at submit time,
the variables are no longer loaded. So, the pages and text boxes
could not be recreated. I solved that problem by modifying the
composite control class to store/retrieve the necessary data in
ViewState.

For item number 3 I simply used an if (! Page.IsPostBack) around the
point where I set the box text to zero. This worked, but later I
tested and determined it is not necessary. Obviously the boxes are
loaded from the ViewState afterwards.

Now I can use the LocateControl routine you showed to get the values
at submit time! Fantastic! Thanks so much for your help.

A note and a question:

1. The above is sufficient for my purposes, but if I allow the page to
be updated (IOW if I don't transfer to another page after the submit),
the page redraws without the tabs. This was fixed by removing the if
(! Page.IsPostBack) from the tab creations. Apparently this is needed
too.

2. My question is if there is now a way I can data bind the text boxes
to some class variables and eliminate the need to extract the value
from each text box individually? Will data binding work
automatically, or will I still have to write code to extract the
values? And is it possible to bind an array to a group of text boxes,
or would I have to bind each element of the array separately.

Scott, thank you again for your help. Now that I have it working, I
can see very well what the issues are, but without help it was
impossible for me to figure it out.

Regards, Russ

On Wed, 30 Jun 2004 22:09:31 -0400, "Scott G."
[quoted text, click to view]

AddThis Social Bookmark Button